|
|
@@ -0,0 +1,206 @@
|
|
|
+<?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提示:处理器类会根据约定自动加载,无需手动配置。");
|
|
|
+ }
|
|
|
+}
|