| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- <?php
- namespace Webman\Console\Commands;
- use Doctrine\Inflector\InflectorFactory;
- use support\Db;
- use Symfony\Component\Console\Command\Command;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Output\OutputInterface;
- use Symfony\Component\Console\Input\InputOption;
- use Symfony\Component\Console\Input\InputArgument;
- use Symfony\Component\Console\Question\ConfirmationQuestion;
- use Webman\Console\Util;
- class MakeModelCommand extends Command
- {
- protected static $defaultName = 'make:model';
- protected static $defaultDescription = 'Make model';
- /**
- * @return void
- */
- protected function configure()
- {
- $this->addArgument('name', InputArgument::REQUIRED, 'Model name');
- $this->addArgument('type', InputArgument::OPTIONAL, 'Type');
- $this->addOption('connection', 'c', InputOption::VALUE_OPTIONAL, 'Select database connection. ');
- }
- /**
- * @param InputInterface $input
- * @param OutputInterface $output
- * @return int
- */
- protected function execute(InputInterface $input, OutputInterface $output): int
- {
- $name = $input->getArgument('name');
- $name = Util::nameToClass($name);
- $type = $input->getArgument('type');
- $connection = $input->getOption('connection');
- $output->writeln("Make model $name");
- if (!($pos = strrpos($name, '/'))) {
- $name = ucfirst($name);
- $model_str = Util::guessPath(app_path(), 'model') ?: 'model';
- $file = app_path() . DIRECTORY_SEPARATOR . $model_str . DIRECTORY_SEPARATOR . "$name.php";
- $namespace = $model_str === 'Model' ? 'App\Model' : 'app\model';
- } else {
- $name_str = substr($name, 0, $pos);
- if($real_name_str = Util::guessPath(app_path(), $name_str)) {
- $name_str = $real_name_str;
- } else if ($real_section_name = Util::guessPath(app_path(), strstr($name_str, '/', true))) {
- $upper = strtolower($real_section_name[0]) !== $real_section_name[0];
- } else if ($real_base_controller = Util::guessPath(app_path(), 'controller')) {
- $upper = strtolower($real_base_controller[0]) !== $real_base_controller[0];
- }
- $upper = $upper ?? strtolower($name_str[0]) !== $name_str[0];
- if ($upper && !$real_name_str) {
- $name_str = preg_replace_callback('/\/([a-z])/', function ($matches) {
- return '/' . strtoupper($matches[1]);
- }, ucfirst($name_str));
- }
- $path = "$name_str/" . ($upper ? 'Model' : 'model');
- $name = ucfirst(substr($name, $pos + 1));
- $file = app_path() . DIRECTORY_SEPARATOR . $path . DIRECTORY_SEPARATOR . "$name.php";
- $namespace = str_replace('/', '\\', ($upper ? 'App/' : 'app/') . $path);
- }
- if (!$type) {
- $database = config('database');
- if (isset($database['default']) && strpos($database['default'], 'plugin.') === 0) {
- $database = false;
- }
- $thinkorm = config('thinkorm');
- if (isset($thinkorm['default']) && strpos($thinkorm['default'], 'plugin.') === 0) {
- $thinkorm = false;
- }
- $type = !$database && $thinkorm ? 'tp' : 'laravel';
- }
- if (is_file($file)) {
- $helper = $this->getHelper('question');
- $question = new ConfirmationQuestion("$file already exists. Do you want to override it? (yes/no)", false);
- if (!$helper->ask($input, $output, $question)) {
- return Command::SUCCESS;
- }
- }
- if ($type == 'tp') {
- $this->createTpModel($name, $namespace, $file, $connection);
- } else {
- $this->createModel($name, $namespace, $file, $connection);
- }
- return self::SUCCESS;
- }
- /**
- * @param $class
- * @param $namespace
- * @param $file
- * @param string|null $connection
- * @return void
- */
- protected function createModel($class, $namespace, $file, $connection = null)
- {
- $path = pathinfo($file, PATHINFO_DIRNAME);
- if (!is_dir($path)) {
- mkdir($path, 0777, true);
- }
- $table = Util::classToName($class);
- $table_val = 'null';
- $pk = 'id';
- $properties = '';
- $connection = $connection ?: 'mysql';
- try {
- $prefix = config("database.connections.$connection.prefix") ?? '';
- $database = config("database.connections.$connection.database");
- $inflector = InflectorFactory::create()->build();
- $table_plura = $inflector->pluralize($inflector->tableize($class));
- $con = Db::connection($connection);
- if ($con->select("show tables like '{$prefix}{$table_plura}'")) {
- $table_val = "'$table'";
- $table = "{$prefix}{$table_plura}";
- } else if ($con->select("show tables like '{$prefix}{$table}'")) {
- $table_val = "'$table'";
- $table = "{$prefix}{$table}";
- }
- $tableComment = $con->select('SELECT table_comment FROM information_schema.`TABLES` WHERE table_schema = ? AND table_name = ?', [$database, $table]);
- if (!empty($tableComment)) {
- $comments = $tableComment[0]->table_comment ?? $tableComment[0]->TABLE_COMMENT;
- $properties .= " * {$table} {$comments}" . PHP_EOL;
- }
- foreach ($con->select("select COLUMN_NAME,DATA_TYPE,COLUMN_KEY,COLUMN_COMMENT from INFORMATION_SCHEMA.COLUMNS where table_name = '$table' and table_schema = '$database' ORDER BY ordinal_position") as $item) {
- if ($item->COLUMN_KEY === 'PRI') {
- $pk = $item->COLUMN_NAME;
- $item->COLUMN_COMMENT .= "(主键)";
- }
- $type = $this->getType($item->DATA_TYPE);
- $properties .= " * @property $type \${$item->COLUMN_NAME} {$item->COLUMN_COMMENT}\n";
- }
- } catch (\Throwable $e) {
- echo $e->getMessage() . PHP_EOL;
- }
- $properties = rtrim($properties) ?: ' *';
- $model_content = <<<EOF
- <?php
- namespace $namespace;
- use support\Model;
- /**
- $properties
- */
- class $class extends Model
- {
- /**
- * The connection name for the model.
- *
- * @var string|null
- */
- protected \$connection = '$connection';
-
- /**
- * The table associated with the model.
- *
- * @var string
- */
- protected \$table = $table_val;
- /**
- * The primary key associated with the table.
- *
- * @var string
- */
- protected \$primaryKey = '$pk';
- /**
- * Indicates if the model should be timestamped.
- *
- * @var bool
- */
- public \$timestamps = false;
-
-
- }
- EOF;
- file_put_contents($file, $model_content);
- }
- /**
- * @param $class
- * @param $namespace
- * @param $file
- * @param string|null $connection
- * @return void
- */
- protected function createTpModel($class, $namespace, $file, $connection = null)
- {
- $path = pathinfo($file, PATHINFO_DIRNAME);
- if (!is_dir($path)) {
- mkdir($path, 0777, true);
- }
- $table = Util::classToName($class);
- $table_val = 'null';
- $pk = 'id';
- $properties = '';
- $connection = $connection ?: 'mysql';
- try {
- $prefix = config("thinkorm.connections.$connection.prefix") ?? '';
- $database = config("thinkorm.connections.$connection.database");
- $con = \think\facade\Db::connect($connection);
- if ($con->query("show tables like '{$prefix}{$table}'")) {
- $table = "{$prefix}{$table}";
- $table_val = "'$table'";
- } else if ($con->query("show tables like '{$prefix}{$table}s'")) {
- $table = "{$prefix}{$table}s";
- $table_val = "'$table'";
- }
- $tableComment = $con->query('SELECT table_comment FROM information_schema.`TABLES` WHERE table_schema = ? AND table_name = ?', [$database, $table]);
- if (!empty($tableComment)) {
- $comments = $tableComment[0]['table_comment'] ?? $tableComment[0]['TABLE_COMMENT'];
- $properties .= " * {$table} {$comments}" . PHP_EOL;
- }
- foreach ($con->query("select COLUMN_NAME,DATA_TYPE,COLUMN_KEY,COLUMN_COMMENT from INFORMATION_SCHEMA.COLUMNS where table_name = '$table' and table_schema = '$database' ORDER BY ordinal_position") as $item) {
- if ($item['COLUMN_KEY'] === 'PRI') {
- $pk = $item['COLUMN_NAME'];
- $item['COLUMN_COMMENT'] .= "(主键)";
- }
- $type = $this->getType($item['DATA_TYPE']);
- $properties .= " * @property $type \${$item['COLUMN_NAME']} {$item['COLUMN_COMMENT']}\n";
- }
- } catch (\Throwable $e) {
- echo $e->getMessage() . PHP_EOL;
- }
- $properties = rtrim($properties) ?: ' *';
- $model_content = <<<EOF
- <?php
- namespace $namespace;
- use think\Model;
- /**
- $properties
- */
- class $class extends Model
- {
- /**
- * The connection name for the model.
- *
- * @var string|null
- */
- protected \$connection = '$connection';
-
- /**
- * The table associated with the model.
- *
- * @var string
- */
- protected \$table = $table_val;
- /**
- * The primary key associated with the table.
- *
- * @var string
- */
- protected \$pk = '$pk';
-
- }
- EOF;
- file_put_contents($file, $model_content);
- }
- /**
- * @param string $type
- * @return string
- */
- protected function getType(string $type)
- {
- if (strpos($type, 'int') !== false) {
- return 'integer';
- }
- switch ($type) {
- case 'varchar':
- case 'string':
- case 'text':
- case 'date':
- case 'time':
- case 'guid':
- case 'datetimetz':
- case 'datetime':
- case 'decimal':
- case 'enum':
- return 'string';
- case 'boolean':
- return 'integer';
- case 'float':
- return 'float';
- default:
- return 'mixed';
- }
- }
- }
|