setName('generate') ->setDescription('生成后台基础crud') ->addOption('title', 't', Option::VALUE_REQUIRED, '标题') ->addOption('name', null, Option::VALUE_REQUIRED, '权限标识') ->addOption('controller', null, Option::VALUE_REQUIRED, '控制器命名空间'); } protected function setInfo(string $controller, string $name, string $title) { $this->name = $name; $this->controller = $controller; $this->title = $title; $this->controllerFullPath = $this->getControllerPathName(); $this->viewDir = $this->getViewDirName(); $this->jsFullDir = $this->getJsFullDirName(); $this->jsDir = $this->getJsDirName(); $controllerPath = explode('/', trim($controller, '/')); $this->className = $controllerPath[count($controllerPath) - 1]; $namespace = 'app\\controller\\'.implode('\\', array_slice($controllerPath, 0, count($controllerPath) - 1)); $this->namespace = $namespace; } protected function execute(Input $input, Output $output) { $title = $input->getOption('title') ? trim($input->getOption('title')) : ''; $name = $input->getOption('name') ? trim($input->getOption('name')) : ''; $controller = $input->getOption('controller') ? trim($input->getOption('controller')) : ''; $this->setInfo($controller, $name, $title); try { $output->writeln('开始创建'); $output->writeln('1.菜单表生成数据...'); $dbRes = $this->createDb([ 'title' => $title, 'name' => $name, 'controller' => $controller ]); $successList = []; if ($dbRes) { $output->info('菜单表数据生成成功!'); $successList[] = '菜单数据生成!'; } else { $output->warning('菜单表数据生成失败'); } $output->writeln('2.生成控制器...'); if (is_file($this->controllerFullPath)) { $output->error('控制器: '.$controller.' 已存在!'); } if (!is_dir(dirname($this->controllerFullPath))) { mkdir(dirname($this->controllerFullPath), 0755, true); } // 生成控制器 file_put_contents($this->controllerFullPath, $this->buildController()); $output->info($this->controllerFullPath.' 控制器生成成功!'); $successList[] = '创建文件:'.$this->controllerFullPath; $output->writeln('3.生成视图文件...'); if (!is_dir($this->viewDir)) { mkdir($this->viewDir, 0755, true); } foreach (['index', 'add', 'edit'] as $action) { $actionHtml = sprintf('%s/%s.html', $this->viewDir, $action); if (is_file($actionHtml)) { $output->error($actionHtml.' 视图文件已存在!'); } file_put_contents($actionHtml, $this->buildView($action)); $output->info($actionHtml.' 文件创建成功'); $successList[] = '创建文件:'.$actionHtml; } $output->info('视图文件生成成功!'); $jsPath = sprintf('%s/%s.js', $this->jsFullDir, unCamelize($this->className, '_')); $output->writeln('4.生成js文件...'); if (!is_dir($this->jsFullDir)) { mkdir($this->jsFullDir, 0755, true); } file_put_contents($jsPath, $this->buildJs()); $output->info($jsPath.' js文件创建成功!'); $successList[] = '创建文件:'.$jsPath; $output->newLine(); $output->writeln('信息汇总'); // 汇总信息 foreach ($successList as $success) { $output->info($success); } $output->newLine(); $output->info(sprintf('此时可访问路径查看是否创建成功 /%s/index', unCamelize($controller))); $output->newLine(); $output->warning('请注意,控制器中 $noNeedRight 默认开启了所有权限,如需纳入权限控制,请删除并在角色中选择对应权限'); // 指令输出 $output->info('创建完成'); } catch (\Exception $e) { $output->error($e->getMessage()); } } /** * 构建控制器内容 * * @return array|false|string|string[] */ protected function buildController() { $controllerStubPath = __DIR__.DIRECTORY_SEPARATOR.'stubs/controller.stub'; $stub = file_get_contents($controllerStubPath); return str_replace(['{%className%}', '{%namespace%}'], [ $this->className, $this->namespace, ], $stub); } /** * 构建视图文件内容 * * @param string $action * @return array|false|string|string[] */ protected function buildView(string $action) { $actionStubPath = __DIR__.DIRECTORY_SEPARATOR.'stubs/'.$action.'.stub'; $stub = file_get_contents($actionStubPath); return str_replace(['{%path%}', '{%jsPath%}'], [ '/'.unCamelize($this->controller), $this->jsDir.'/'.unCamelize($this->className, '_').'.js', ], $stub); } /** * 构建js文件内容 * * @return false|string */ protected function buildJs() { $actionStubPath = __DIR__.DIRECTORY_SEPARATOR.'stubs/js.stub'; return file_get_contents($actionStubPath); } /** * 获取控制器完整路径 * * @return string */ protected function getControllerPathName(): string { return $this->app->getBasePath().'controller/'.ltrim(str_replace('\\', '/', $this->controller), '/').'.php'; } /** * 获取对应view完整目录 * * @return string */ protected function getViewDirName(): string { return $this->app->getRootPath().'view/'.ltrim(unCamelize($this->controller, '_'), '/'); } /** * 获取对应js完整目录 * * @return string */ protected function getJsFullDirName(): string { $dir = $this->app->getRootPath().'public/static/'.ltrim(unCamelize($this->controller, '_'), '/'); return str_replace('/manager/', '/manager/js/', $dir); } /** * 获取对应js相对目录 * * @return string */ protected function getJsDirName(): string { return explode('/manager/', $this->jsFullDir)[1] ?? ''; } /** * 自动添加菜单表数据 * * @param array $data * @return bool * @throws \Exception */ public function createDb(array $data): bool { $menuTable = 'menu'; $now = date('Y-m-d H:i:s'); if (!isset($data['title']) || !isset($data['name']) || !isset($data['controller'])) { throw new \Exception('参数错误 请添加:--title 标题 --name 权限标识,如aaa/bbb --controller 控制器 如manager/aaa/Bbb'); } if (empty($data['title']) || empty($data['name']) || empty($data['controller'])) { throw new \Exception('参数错误 请添加:--title 标题 --name 权限标识,如aaa/bbb --controller 控制器 如manager/aaa/Bbb'); } // 检查权限标识是否已存在 $already = Db::name('menu')->where('name', $data['name'])->whereOr('title', $data['title'])->count(); if ($already) { throw new \Exception('菜单名称或标识已存在'); } $href = unCamelize($data['controller']); $insertMaster = [ 'pid' => 0, 'title' => $data['title'], //名称 'icon' => $data['icon'] ?? 'fa-align-justify', //菜单图标 'name' => $data['name'], //权限标识 'href' => $href.'/index',//链接 'type' => 'menu', 'is_show' => 1, 'status' => 1, 'remark' => 'command generate', 'created_at' => $now, ]; $masterId = Db::name($menuTable)->insertGetId($insertMaster); $masterPath = sprintf(',0,%d,', $masterId); Db::name($menuTable)->where('id', $masterId)->update([ 'path' => $masterPath ]); $insertName = trim($data['name'], '/'); $insertHref = '/'.trim($href, '/'); $actionArr = $this->actionList(); // 基于权限标识生成下级列表 默认index add del edit modify $insertAll = []; foreach (array_keys($actionArr) as $action) { $insertAll[] = [ 'pid' => $masterId, 'title' => $actionArr[$action]['title'], //名称 'icon' => '', //菜单图标 'name' => $insertName.':'.$action, //权限标识 'href' => $insertHref.'/'.$action,//链接 'type' => 'action', 'is_show' => 1, 'status' => 1, 'remark' => 'command generate', 'path' => $masterPath,//此时的path为负极path 'created_at' => $now, ]; } // 插入自己菜单 Db::name($menuTable)->insertAll($insertAll); // 批量更新自己菜单path Db::execute("update bee_$menuTable set `path`=concat(`path`, `id`, ',') where pid=$masterId"); return true; } protected function actionList(): array { return [ 'index' => ['title' => '查看'], 'add' => ['title' => '添加'], 'edit' => ['title' => '编辑'], 'del' => ['title' => '删除'], 'modify' => ['title' => '属性设置'], 'sort' => ['title' => '排序'], ]; } }