| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- <?php
- namespace App\Console\Commands;
- use Illuminate\Console\Command;
- use Illuminate\Support\Facades\File;
- use Illuminate\Support\Str;
- class GenerateProtoRouteCommand extends Command
- {
- protected $signature = 'proto:route {--force : 强制覆盖现有配置}';
- protected $description = '生成 Protobuf 路由配置';
- protected $protoDir = 'protophp/Uraus/Kku';
- protected $configPath = 'config/proto_route.php';
- public function handle()
- {
- $this->info('开始扫描 Protobuf 请求定义...');
- // 获取所有模块
- $modules = $this->scanModules();
- // 生成配置数组
- $config = $this->generateConfig($modules);
- // 生成配置文件
- $this->generateConfigFile($config);
- $this->info('Protobuf 路由配置生成完成!');
- // 输出提示信息
- $this->showHandlerGuide($modules);
- return Command::SUCCESS;
- }
- protected function scanModules(): array
- {
- $modules = [];
- $baseDir = base_path($this->protoDir);
- // 扫描 Request 目录
- $requestDir = $baseDir . '/Request';
- if (File::isDirectory($requestDir)) {
- // 扫描所有 Request 开头的 PHP 文件
- $files = File::glob($requestDir . '/Request*.php');
- foreach ($files as $file) {
- $className = basename($file, '.php');
- if (strpos($className, 'Request') === 0 && $className !== 'Request') {
- // 解析模块和方法
- $this->parseRequestClass($className, $modules);
- }
- }
- }
- // 扫描根目录下的 Request 文件
- $rootFiles = File::glob($baseDir . '/Request*.php');
- foreach ($rootFiles as $file) {
- $className = basename($file, '.php');
- if (strpos($className, 'Request') === 0 && $className !== 'Request') {
- // 解析模块和方法
- $this->parseRequestClass($className, $modules);
- }
- }
- return $modules;
- }
- /**
- * 解析请求类名,提取模块和方法
- *
- * @param string $className 请求类名,如 RequestPublicLogin
- * @param array &$modules 模块数组,按引用传递
- * @return void
- */
- protected function parseRequestClass(string $className, array &$modules): void
- {
- // 如果是 RequestPublicLogin 格式,则直接处理
- if ($className === 'RequestPublicLogin') {
- if (!isset($modules['public'])) {
- $modules['public'] = [];
- }
- if (!in_array('login', $modules['public'])) {
- $modules['public'][] = 'login';
- }
- return;
- }
- // 如果是 Request_RequestPublicLogin 格式,则跳过
- if (strpos($className, 'Request_Request') === 0) {
- return;
- }
- // 移除 Request 前缀
- $name = substr($className, strlen('Request'));
- // 检查是否包含下划线,表示有方法部分
- if (strpos($name, '_') !== false) {
- // 格式如 Public_Login
- list($module, $method) = explode('_', $name, 2);
- } else {
- // 如果是 RequestPublicLogin 这样的格式,需要特殊处理
- if (preg_match('/^([A-Z][a-z]+)([A-Z].*)$/', $name, $matches)) {
- $module = $matches[1]; // Public
- $method = $matches[2]; // Login
- } else {
- // 其他格式,如果没有明显的分隔,则整个作为模块
- $module = $name;
- $method = '';
- }
- }
- // 模块名首字母小写
- $moduleKey = lcfirst($module);
- // 方法名转为小写下划线格式
- $methodKey = Str::snake(lcfirst($method));
- // 如果方法为空,则不添加
- if (!empty($methodKey)) {
- if (!isset($modules[$moduleKey])) {
- $modules[$moduleKey] = [];
- }
- if (!in_array($methodKey, $modules[$moduleKey])) {
- $modules[$moduleKey][] = $methodKey;
- }
- }
- }
- protected function extractMethodsFromContent(string $content): array
- {
- // 不再从文件内容中提取方法,而是从类名中解析
- return [];
- }
- protected function scanMethodFields(string $moduleDir): array
- {
- return []; // 不再需要扫描子目录
- }
- protected function generateConfig(array $modules): array
- {
- $routes = [];
- foreach ($modules as $field => $methods) {
- if (!empty($methods) && !empty($field)) {
- $routes[$field] = array_values($methods);
- }
- }
- return [
- 'routes' => $routes,
- 'generated_at' => date('P Y-m-d H:i:s'),
- 'conventions' => [
- 'handler_namespace' => 'App\\Module\\AppGame\\Handler',
- 'request_namespace' => 'Uraus\\Kku\\Request',
- 'response_namespace' => 'Uraus\\Kku\\Response'
- ]
- ];
- }
- protected function generateConfigFile(array $config): void
- {
- $configContent = "<?php\n\nreturn " . var_export($config, true) . ";\n";
- $configPath = config_path('proto_route.php');
- if (File::exists($configPath) && !$this->option('force')) {
- if (!$this->confirm('配置文件已存在,是否覆盖?')) {
- $this->warn('操作已取消');
- return;
- }
- }
- File::put($configPath, $configContent);
- $this->info("配置文件已生成:{$configPath}");
- }
- protected function showHandlerGuide(array $modules): void
- {
- $this->info("\n按照以下约定创建处理器类:\n");
- foreach ($modules as $field => $methods) {
- if (empty($methods)) {
- continue;
- }
- $moduleName = ucfirst($field);
- $this->line("\n模块: {$moduleName} (字段: {$field})");
- foreach ($methods as $method) {
- $methodName = Str::studly($method);
- $handlerClass = "App\\Module\\AppGame\\Handler\\{$moduleName}\\{$methodName}Handler";
- $requestClass = "Uraus\\Kku\\Request\\Request{$moduleName}" . ($method ? "_" . Str::studly($method) : "");
- $responseClass = "Uraus\\Kku\\Response\\Response{$moduleName}" . ($method ? "_" . Str::studly($method) : "");
- $this->line("\n 方法: {$method}");
- $this->line(" - Handler: {$handlerClass}");
- $this->line(" - Request: {$requestClass}");
- $this->line(" - Response: {$responseClass}");
- }
- }
- $this->info("\n提示:处理器类会根据约定自动加载,无需手动配置。");
- }
- }
|