命令demo
php think hello(指令) --table 表名
代码如下
<?php declare (strict_types=1);namespace app\command;use DateTime; use think\console\Command; use think\console\Input; use think\console\input\Option; use think\console\Output; use think\facade\Db; use think\helper\Str;class Hello extends Command {protected $rules = [];#命名空间private $namespace = 'app\\validate';#文件名称private $fileName = '';protected function setFileName(){$this->fileName = Str::studly($this->table) . "Validate";}protected function configure(){// 指令配置$this->setName('hello')->addOption('table', null, Option::VALUE_REQUIRED, '表名')->setDescription('自动生成验证器');}protected function execute(Input $input, Output $output){try {$this->namespace = 'app\\validate';if (!$input->hasOption('table')) {throw new \think\Exception('--table参数不能为空', 10006);}$this->table = $input->getOption('table');$this->setFileName();$database = config('database.connections.mysql.database');$tableArr = Db::query("SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = '{$database}' and TABLE_NAME = '{$this->table}';");if (0 === count($tableArr)) {throw new \think\Exception($this->table . "表不存在", 10006);}$comments = Db::query("SHOW FULL COLUMNS FROM `{$this->table}`");foreach ($comments as $v) {if ('PRI' === $v['Key']) continue;$this->rules[$v['Field']] = ['name' => $this->getColumnName($v), "rule" => []];$columnFullType = $v['Type'];$preg = "/^(\w+)\(?/";if (preg_match($preg, $columnFullType, $matches)) {$columnType = $matches[1];} else {throw new \think\Exception('未找到字段类型', 10006);} // if ('NO' === $v['Null']) { // $this->rules[$v['Field']]['rule'][] = 'require'; // }$this->rules[$v['Field']]['rule'][] = 'require';if ($this->containsPhoneOrMobile($v['Comment'])) {$this->rules[$v['Field']]['rule'][] = 'mobile';}if ($this->email($v['Comment'])) {$this->rules[$v['Field']]['rule'][] = 'email';}switch ($columnType) {case 'int':case 'bigint':case 'tinyint':$this->setIntColumnRule($v, $columnType);break;case 'char':case 'varchar':$this->setCharColumnRule($v, $columnType);break;case 'tinytext':case 'text':case 'mediumtext':case 'longtext':$this->setTextColumnRule($v, $columnType);break;case 'float':case 'double':throw new \think\Exception('浮点型只支持decimal类型', 10006);case 'decimal':$this->setFloatColumnRule($v, $columnType);break;case 'date':$this->rules[$v['Field']]['rule'][] = 'checkDateYmd:' . $this->getColumnName($v) . '时间格式不对';break;case 'datetime':$this->rules[$v['Field']]['rule'][] = 'checkDateYmdHis:' . $this->getColumnName($v) . '时间格式不对';break;default:throw new \think\Exception("未找到字段{$columnType}类型请完善", 10006);}}$content = $this->generateValidatorContent();!is_dir($this->namespace) && mkdir($this->namespace, 0755, true);$pathname = $this->namespace . '\\' . $this->fileName;if (is_file($pathname . '.php')) {throw new \think\Exception("该文件已经存在" . $pathname. '.php', 10006);}file_put_contents($pathname . '.php', $content);$output->writeln("创建成功");} catch (\Throwable $e) {$output->writeln($e->getMessage());}}protected function setIntColumnRule($v, $columnType){if ($this->unsigned($v['Type'])) {$this->rules[$v['Field']]['rule'][] = 'egt:0';$this->rules[$v['Field']]['rule'][] = 'number';$this->rules[$v['Field']]['rule'][] = 'between:' . $this->getIntBetween($columnType, 'unsignen');} else {$this->rules[$v['Field']]['rule'][] = 'integer';$this->rules[$v['Field']]['rule'][] = 'between:' . $this->getIntBetween($columnType, 'signen');}}protected function setTextColumnRule($v, $columnType){$this->rules[$v['Field']]['rule'][] = $this->getTextBetween($columnType);}function containsPhoneOrMobile($str){$lowerStr = strtolower($str);if (strpos($lowerStr, 'phone') !== false) {return true;}if (mb_strpos($lowerStr, '手机号') !== false) {return true;}return false;}function email($str){$lowerStr = strtolower($str);if (strpos($lowerStr, 'email') !== false) {return true;}if (mb_strpos($lowerStr, '邮箱') !== false) {return true;}return false;}protected function setCharColumnRule($v, $columnType){$preg = "/^(?:var)?char\((\d+)\)/";if (preg_match($preg, $v['Type'], $matches)) {$charLength = $matches[1];} else {throw new \think\Exception('char未匹配到长度', 10006);}$this->rules[$v['Field']]['rule'][] = 'length:0,' . $charLength;}protected function setFloatColumnRule($v, $columnType){$preg = "/^decimal\((\d+),(\d+)\)/";if (preg_match($preg, $v['Type'], $matches)) {if ("2" !== $matches[2]) {throw new \think\Exception('decimal必须小数点两位', 10006);}$float = $matches[1];} else {throw new \think\Exception('decimal不能正确匹配', 10006);}$columnName = $this->getColumnName($v);if ($this->unsigned($v['Type'])) {$this->rules[$v['Field']]['rule'][] = "checkFloat2:{$float}@{$columnName}小数点后面最多两位的数字";} else {$this->rules[$v['Field']]['rule'][] = "checkUnsignedFloat2:{$float}@{$columnName}小数点后面最多两位的数字";}}public function getIntBetween($type, $unsignen){if (isset($this->intArrBetween[$type][$unsignen])) {return $this->intArrBetween[$type][$unsignen];}throw new \think\Exception('未找到' . $type . '字段类型的取值范围', 10006);}public function getTextBetween($type){if (isset($this->textArrBetween [$type])) {return $this->textArrBetween [$type];}throw new \think\Exception('未找到' . $type . '字段类型的取值范围', 10006);}protected function unsigned($string){if (strpos($string, 'unsigned') !== false) return true;return false;}protected function getColumnName($columnData){$Comment = $columnData['Comment'];$preg = "/^([^-]*)-?/";if (preg_match($preg, $Comment, $matches)) {return $matches[1] === '' ? $columnData['Field'] : $matches[1];} else {return $columnData['Field'];}}protected function generateValidatorContent(){$ruleStrContent = <<<RULEprotected \$rule = [ REPLACE];\n RULE;$messageStrContent = <<<CONTENTprotected \$message = [ REPLACE];\n CONTENT;$ruleStr = '';$contentStr = '';foreach ($this->rules as $k => $v) {$ruleContent = implode("|", $v['rule']);$ruleStr .= "\t\t\t'{$k}' => '{$ruleContent}',#{$v['name']}\n";foreach ($v['rule'] as $key => $value) {$ruleMsg = explode(':', $value);$msg = '';switch ($ruleMsg[0]) {case 'number':$msg = "必须是正整数";break;case 'date':$msg = "日期格式不对";break;case 'between':$fanwei = str_replace(',', '~', $ruleMsg[1]);$msg = "必须在{$fanwei}内";break;case 'integer':$msg = "必须为整数";break;case 'egt':$msg = "大于等于0";break;case 'require':$msg = "不能为空";break;case 'mobile':$msg = "格式错误";break;case 'email':$msg = "格式错误";break;}if ($msg) {$contentStr .= "\t\t\t'{$k}.{$ruleMsg[0]}' => '{$v['name']}{$msg}',#{$v['name']}\n";}}}$ruleStr = str_replace('REPLACE', $ruleStr, $ruleStrContent);$messageStr = str_replace('REPLACE', $contentStr, $messageStrContent);return "<?php namespace $this->namespace; use DateTime; use think\Validate;class " . Str::studly($this->table) . "Validate extends Validate {$ruleStr$messageStrpublic function sceneAdd(){return \$this->only([]);}public function sceneEdit(){return \$this->only([]);} protected function checkFloat2(\$value, \$rule, \$data=[]){\$arr = explode('@',\$rule);\$pattern = '/^(0|[1-9]\d*)(\.\d{1,2})?$/';if (!preg_match(\$pattern, \$value)) {return \$arr[1];}if(strlen((int)\$value)>(\$arr[0]-2)){return \$arr[1];}return true;}protected function checkUnsignedFloat2(\$value, \$rule, \$data=[]){\$arr = explode('@',\$rule);\$pattern = '/^(?:\-)?(0|[1-9]\d*)(\.\d{1,2})?$/';if (!preg_match(\$pattern, \$value)) {return \$arr[1];}if(strlen((int)\$value)>(\$arr[0]-2)){return \$arr[1];}return true;}protected function checkDateYmd(\$value, \$rule, \$data = []){DateTime::createFromFormat('Y-m-d', \$value);\$errors = DateTime::getLastErrors();if ((\$errors['warning_count'] + \$errors['error_count']) > 0) {return \$rule;}return true;}protected function checkDateYmdHis(\$value, \$rule, \$data = []){DateTime::createFromFormat('Y-m-d H:i:s', \$value);\$errors = DateTime::getLastErrors();if ((\$errors['warning_count'] + \$errors['error_count']) > 0) {return \$rule;}return true;}} ";}private $intArrBetween = ['int' => ['unsignen' => '0,4294967295','signen' => "-2147483648,2147483647",],'bigint' => ['unsignen' => '0,12345678901234567890','signen' => "-1234567890123456789,1234567890123456789",],'tinyint' => ['unsignen' => '0,255','signen' => "-128,127",]];private $textArrBetween = ['tinytext' => '0,255','text' => '0,65535','mediumtext' => '0,16777215','longtext' => '0,4294967295',]; }