Files
ulthon_admin/extend/base/common/command/CurdBase.php
2026-03-26 20:22:34 +08:00

197 lines
7.2 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace base\common\command;
use app\admin\service\curd\BuildCurdService;
use app\common\console\Command;
use app\common\tools\PathTools;
use think\console\Input;
use think\console\input\Option;
use think\console\Output;
use think\Exception;
use think\facade\App;
class CurdBase extends Command
{
protected function configure()
{
parent::configure();
$this->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'
<info>CURD 命令使用示例</info>
<comment>示例 1首次生成基本用法</comment>
<info>php think curd -t daka_record</info>
说明:直接生成到项目目录,如文件已存在会跳过
<comment>示例 2增量更新已有业务代码</comment>
<info>php think curd -t daka_record -r</info>
说明:生成到 runtime 临时目录,用于手动对比并合并新增字段代码(避免覆盖业务逻辑)
<comment>示例 3带前缀的表名</comment>
<info>php think curd -t ul_daka_record</info>
说明:自动识别并去除前缀
<comment>示例 4强制覆盖谨慎使用</comment>
<info>php think curd -t daka_record -f</info>
说明:覆盖已存在的文件,<error>会丢失手动修改的内容</error>
<comment>示例 5删除已生成的文件</comment>
<info>php think curd -t daka_record -d</info>
说明:删除之前生成的所有文件(会要求确认)
注意:<error>这是删除文件,不是删除数据库记录</error>
<comment>常见错误及解决:</comment>
错误:表不存在
→ 先创建表php think scheme:sync
→ 或使用迁移php think migrate:run
错误Scheme 与数据库不一致
→ 同步 Schemephp 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;
}
}
}