setName('curd') ->addOption('table', 't', Option::VALUE_REQUIRED, '主表名', null) ->addOption('controllerFilename', 'c', Option::VALUE_REQUIRED, '控制器文件名', null) ->addOption('modelFilename', 'm', Option::VALUE_REQUIRED, '主表模型文件名', null) // ->addOption('force', 'f', Option::VALUE_NONE, '强制覆盖模式') ->addOption('delete', 'd', Option::VALUE_NONE, '删除模式') ->addOption('runtime', 'r', Option::VALUE_NONE, '临时生成(生成到 runtime 目录)') ->addOption('examples', null, Option::VALUE_NONE, '显示使用示例') ->setDescription('一键生成 CURD 代码(控制器、模型、视图、JS)'); } protected function getExamplesText(): string { return <<<'EXAMPLES' CURD 命令使用示例 示例 1:首次生成(基本用法) php think curd -t daka_record 说明:直接生成到项目目录,如文件已存在会跳过 示例 2:增量更新(已有业务代码) php think curd -t daka_record -r 说明:生成到 runtime 临时目录,用于手动对比并合并新增字段代码(避免覆盖业务逻辑) 示例 3:带前缀的表名 php think curd -t ul_daka_record 说明:自动识别并去除前缀 示例 4:强制覆盖(谨慎使用) php think curd -t daka_record -f 说明:覆盖已存在的文件,会丢失手动修改的内容 示例 5:删除已生成的文件 php think curd -t daka_record -d 说明:删除之前生成的所有文件(会要求确认) 注意:这是删除文件,不是删除数据库记录 常见错误及解决: 错误:表不存在 → 先创建表:php think scheme:sync → 或使用迁移:php think migrate:run 错误:Scheme 与数据库不一致 → 同步 Scheme:php think scheme:sync EXAMPLES; } protected function execute(Input $input, Output $output) { // 显示使用示例 if ($input->hasOption('examples')) { $output->writeln($this->getExamplesText()); return true; } $table = $input->getOption('table'); $controllerFilename = $input->getOption('controllerFilename'); $modelFilename = $input->getOption('modelFilename'); $force = 0; $delete = 0; if ($input->hasOption('force')) { $force = 1; } if ($input->hasOption('delete')) { $delete = 1; } if (empty($table)) { $output->error('请设置主表'); return false; } // 收集警告信息 $warnings = []; try { $build = (new BuildCurdService()) ->setTable($table) ->setForce($force); $runtime_path = ''; if ($input->hasOption('runtime')) { $runtime_path = App::getRuntimePath() . 'source' . DS . 'build' . DS . date('YmdHis') . DS; PathTools::intiDir($runtime_path . 'a.temp'); $build->setRootDir($runtime_path); } $columns = $build->getTableColumns(); $relations = []; foreach ($columns as $field => $column) { if (isset($column['formType']) && $column['formType'] == 'relation') { $define = $column['define']; if (!isset($define['table'])) { $error = "关联字段{$field}没有设置关联表名称"; $output->error($error); $warnings[] = ['message' => $error]; return false; } $relations[] = [ 'table' => $define['table'], 'foreignKey' => $field, 'primaryKey' => $define['primaryKey'] ?? null, 'modelFilename' => $define['modelFilename'] ?? null, 'onlyFileds' => isset($define['onlyFileds']) ? explode('|', $define['onlyFileds']) : [], 'relationBindSelect' => $define['relationBindSelect'] ?? null, ]; } } !empty($controllerFilename) && $build = $build->setControllerFilename($controllerFilename); !empty($modelFilename) && $build = $build->setModelFilename($modelFilename); foreach ($relations as $relation) { $build = $build->setRelation($relation['table'], $relation['foreignKey'], $relation['primaryKey'], $relation['modelFilename'], $relation['onlyFileds'], $relation['relationBindSelect']); } $build = $build->render(); $fileList = $build->getFileList(); $result = []; if (!$delete) { if ($force) { $output->writeln('>>>>>>>>>>>>>>>'); foreach ($fileList as $key => $val) { $output->writeln($key); } $output->writeln('>>>>>>>>>>>>>>>'); if (!$output->confirm($input, '确定强制生成上方所有文件? 如果文件存在会直接覆盖。', true)) { $output->comment('已取消。'); return false; } } $result = $build->create(); $output->info('自动生成CURD成功'); } else { $output->writeln('>>>>>>>>>>>>>>>'); foreach ($fileList as $key => $val) { $output->writeln($key); } $output->writeln('>>>>>>>>>>>>>>>'); if (!$output->confirm($input, '确定删除上方所有文件? ', true)) { $output->comment('已取消。'); return false; } $result = $build->delete(); $output->info('>>>>>>>>>>>>>>>'); $output->info('删除自动生成CURD文件成功'); } $output->info('>>>>>>>>>>>>>>>'); foreach ($result as $vo) { $output_endfix = ''; if ($input->hasOption('runtime')) { $base_path = str_replace($runtime_path, '', $vo); $root_path = App::getRootPath(); $output_endfix = PHP_EOL . 'ORIGIN:>>' . str_repeat(' ', 26) . ' ' . $root_path . $base_path . ' '; } $output->info($vo . $output_endfix . ' '); } } catch (\Exception $e) { $output->error($e->getMessage()); return false; } } }