# Laravel + Laravel-S 后端 API 项目开发规范 ## 项目概述 本项目是一个基于 Laravel 框架开发的纯后端 API 系统,使用 `hhxsv5/laravel-s` 作为粘合剂,将 Swoole 与 Laravel 框架完美结合,提供高性能的异步服务能力。项目采用模块化开发架构,使用 `nwidart/laravel-modules` 扩展实现业务模块化管理。 ## 技术栈 - **PHP**: 主要开发语言 - **Laravel**: Web 应用框架 - **Laravel-S (hhxsv5/laravel-s)**: Swoole 集成扩展 - **Swoole**: 高性能 PHP 协程框架 - **JWT (tymon/jwt-auth)**: 用户认证 - **nwidart/laravel-modules**: 模块化开发扩展 - **MySQL**: 关系型数据库 ## 模块化架构 ### 模块分类 项目分为两类模块: 1. **基础模块 (Base Modules)** - **Auth**: 认证授权模块(用户、角色、权限) - **System**: 系统配置模块(配置、日志、字典) - 特点:不使用 `nwidart/laravel-modules` 扩展,直接在 Laravel 应用结构中开发 - 位置:`app/` 目录下 2. **业务模块 (Business Modules)** - 使用 `nwidart/laravel-modules` 扩展创建 - 位置:`Modules/` 目录下 - 每个业务模块独立拥有完整的 MVC 结构 ### 项目结构 ``` ├── app/ # 基础模块目录 │ ├── Http/ │ │ ├── Controllers/ # 基础模块控制器 │ │ │ ├── Auth/ # 认证相关控制器 │ │ │ │ └── Admin │ │ │ │ │ ├── Auth.php │ │ │ │ │ ├── User.php │ │ │ │ │ ├── Role.php │ │ │ │ │ └── Permission.php │ │ │ └── System/ # 系统相关控制器 │ │ │ └── Admin │ │ │ └── Api │ │ └── Middleware/ # 中间件 │ ├── Models/ # 基础模块模型 │ │ └── Auth/ │ │ ├── User.php │ │ ├── Role.php │ │ └── Permission.php │ └── Services/ # 基础模块服务层 │ └── Auth/ │ ├── AuthService.php │ ├── UserService.php │ ├── RoleService.php │ └── PermissionService.php ├── Modules/ # 业务模块目录 │ ├── ModuleName/ # 业务模块示例 │ │ ├── App/ │ │ │ ├── Http/ │ │ │ │ ├── Controllers/ # 模块控制器 │ │ │ │ │ ├── Admin/ # 后台管理控制器 │ │ │ │ │ └── Api/ # 用户端API控制器 │ │ │ │ ├── Middleware/ # 模块中间件 │ │ │ │ └── Requests/ # 表单验证 │ │ │ ├── Models/ # 模块模型 │ │ │ ├── Services/ # 模块服务层 │ │ │ └── Providers/ # 模块服务提供者 │ │ ├── Database/ │ │ │ ├── migrations/ # 模块迁移文件 │ │ │ └── seeders/ # 模块数据填充 │ │ ├── Routes/ │ │ │ ├── admin.php # 后台管理路由(/admin前缀) │ │ │ └── api.php # 用户端API路由(/api前缀) │ │ ├── Resources/ # API 资源 │ │ ├── config/ # 模块配置文件 │ │ ├── module.json # 模块配置 │ │ └── README.md # 模块说明文档 ├── config/ │ ├── modules.php # 模块配置 │ └── laravels.php # Laravel-S 配置文件 ├── database/ │ ├── migrations/ # 基础模块迁移文件 │ └── seeders/ # 基础模块数据填充 ├── routes/ │ ├── admin.php # 后台管理路由(基础模块) │ └── api.php # 公共 API 路由(基础模块) └── storage/ ├── laravels.conf # Laravel-S 运行时配置 └── laravels.pid # Laravel-S 进程 ID ``` ## 开发规范 ### 1. 控制器层 (Controllers) #### 基础模块控制器 **命名规范:** - 文件路径: `app/Http/Controllers/{Module}/{Name}.php` - 类名: `{Name}` (不加 Controller 后缀) - 命名空间: `App\Http\Controllers\{Module}` **示例:** ```php userService = $userService; } public function index(Request $request) { $result = $this->userService->getList($request->all()); return response()->json($result); } } ``` #### 业务模块控制器 业务模块控制器分为两类: **1. 后台管理控制器** **命名规范:** - 文件路径: `Modules/{ModuleName}/App/Http/Controllers/Admin/{Name}.php` - 类名: `{Name}` (不加 Controller 后缀) - 命名空间: `Modules\{ModuleName}\App\Http\Controllers\Admin` - 访问路径: `/admin/{module}/{resource}` **示例:** ```php postService = $postService; } public function index(Request $request) { $result = $this->postService->getList($request->all()); return response()->json($result); } } ``` **2. 用户端 API 控制器** **命名规范:** - 文件路径: `Modules/{ModuleName}/App/Http/Controllers/Api/{Name}.php` - 类名: `{Name}` (不加 Controller 后缀) - 命名空间: `Modules\{ModuleName}\App\Http\Controllers\Api` - 访问路径: `/api/{module}/{resource}` **示例:** ```php postService = $postService; } public function index(Request $request) { $result = $this->postService->getList($request->all()); return response()->json($result); } } ``` ### 2. 服务层 (Services) #### 基础模块服务 **命名规范:** - 文件路径: `app/Services/{Module}/{Name}Service.php` - 类名: `{Name}Service` - 命名空间: `App\Services\{Module}` **示例:** ```php belongsToMany(Permission::class, 'auth_role_permission'); } } ``` #### 业务模块模型 **命名规范:** - 文件路径: `Modules/{ModuleName}/App/Models/{Name}.php` - 类名: `{Name}` (单数形式) - 命名空间: `Modules\{ModuleName}\App\Models` - 数据表: `{module}_{names}` (复数形式,带模块前缀) **示例:** ```php withRouting( web: __DIR__.'/../routes/web.php', api: __DIR__.'/../routes/api.php', commands: __DIR__.'/../routes/console.php', then: function() { Route::middleware(['api']) ->prefix('admin') ->name('admin.') ->group(base_path('routes/admin.php')); }, health: '/up', ) ->create(); ``` **中间件配置:** ```php withMiddleware(function (Middleware $middleware): void { $middleware->alias([ 'auth.check' => \App\Http\Middleware\AuthCheckMiddleware::class, ]); }) ``` **异常处理配置:** ```php withExceptions(function (Exceptions $exceptions): void { $exceptions->shouldRenderJsonWhen(function(Request $request, Throwable $e){ return $request->expectsJson(); }); }) ``` **事件监听器配置:** ```php withEvents(discover: [ __DIR__ . '/../app/Listeners' ]) ``` **路由示例:** ```php group(function () { Route::apiResource('users', User::class); // 路由名称: admin.users.index, admin.users.store, etc. }); // routes/api.php - 公共 API 路由 use Illuminate\Support\Facades\Route; use App\Http\Controllers\Auth\User; Route::middleware(['auth:api'])->group(function () { Route::apiResource('profile', User::class); }); ``` #### 业务模块路由 业务模块路由包含两个文件,分别定义后台管理和用户端 API 路由: **1. 后台管理路由 (Routes/admin.php)** 文件路径:`Modules/{ModuleName}/Routes/admin.php` ```php group(function () { Route::apiResource('blog/posts', Post::class); }); ``` 路由访问路径:`/admin/{module}/{resource}` **2. 用户端 API 路由 (Routes/api.php)** 文件路径:`Modules/{ModuleName}/Routes/api.php` ```php group(function () { Route::apiResource('blog/posts', Post::class); }); ``` 路由访问路径:`/api/{module}/{resource}` ### 6. 模块创建命令 使用 `nwidart/laravel-modules` 创建新业务模块: ```bash # 创建模块 php artisan module:make ModuleName # 创建带有资源的模块 php artisan module:make ModuleName --resource # 创建多个模块 php artisan module:make Blog Shop Order ``` ### 7. 模块组件创建命令 ```bash # 在指定模块中创建后台管理控制器 php artisan module:make-controller Admin/Post Blog # 在指定模块中创建用户端API控制器 php artisan module:make-controller Api/Post Blog # 在指定模块中创建模型 php artisan module:make-model Post Blog # 在指定模块中创建迁移 php artisan module:make-migration create_posts_table Blog # 在指定模块中创建服务类(需要自定义) # 手动在 Modules/Blog/App/Services/ 目录创建 ``` **注意:** 使用 `module:make-controller` 命令创建的控制器会自动添加 `Controller` 后缀,需要手动重命名文件和类名以移除后缀。 ## API 响应规范 ### 统一响应格式 **成功响应:** ```json { "code": 200, "message": "success", "data": {} } ``` **错误响应:** ```json { "code": 400, "message": "错误信息", "data": null } ``` **分页响应:** ```json { "code": 200, "message": "success", "data": { "list": [], "total": 100, "page": 1, "page_size": 20 } } ``` **树形响应:** ```json { "code": 200, "message": "success", "data": [ {...,children: [ {...} ]}, {...,children: [ {...} ]} ] } ``` ### HTTP 状态码规范 - `200 OK`: 请求成功 - `201 Created`: 创建成功 - `204 No Content`: 删除成功 - `400 Bad Request`: 请求参数错误 - `401 Unauthorized`: 未认证 - `403 Forbidden`: 无权限 - `404 Not Found`: 资源不存在 - `422 Unprocessable Entity`: 表单验证失败 - `500 Internal Server Error`: 服务器错误 ## Laravel-S / Swoole 开发注意事项 ### 1. 长生命周期注意事项 由于 Swoole 是长生命周期运行,需注意以下几点: **避免使用静态变量:** ```php // ❌ 错误 public function handle() { static $counter = 0; // 会累积,不会重置 } // ✅ 正确 public function handle() { $counter = 0; // 每次请求重新初始化 } ``` **避免使用全局变量:** - 不要依赖 `$_GET`, `$_POST` 等超全局变量 - 使用 Laravel 的 `Request` 对象获取请求数据 ### 2. 连接池管理 数据库、Redis 等连接需要正确管理,避免连接泄漏。 **配置连接池:** 在 `config/laravels.php` 中配置: ```php 'swoole' => [ 'enable_coroutine' => true, 'worker_num' => 4, 'max_request' => 5000, 'max_request_grace' => 500, ] ``` ### 3. 热重载机制 开发环境可以使用文件监控实现热重载: ```bash # 使用 bin/laravels reload php bin/laravels reload # 或使用文件监控 bin/fswatch # Linux/Mac bin/inotify # Linux ``` ### 4. 定时器 使用 Swoole 定时器时,要确保定时器在合适的时机清除: ```php \Swoole\Timer::after(5000, function() { // 5秒后执行 }); $timerId = \Swoole\Timer::tick(1000, function() { // 每秒执行 return false; // 返回 false 停止定时器 }); ``` ## 数据库规范 ### 迁移文件 #### 基础模块迁移 - 文件路径: `database/migrations/` - 迁移文件命名: `{YYYY_MM_DD_HHMMSS}_{description}.php` - 表命名: `{module}_{table_names}` (模块名小写 + 下划线 + 表名复数,所有模块表都必须带模块名前缀) **表命名示例:** - Auth 模块: `auth_users`, `auth_roles`, `auth_permissions`, `auth_role_permission` - System 模块: `system_setting`, `system_logs`, `system_dictionaries` **迁移文件示例:** ```php id(); $table->string('name'); $table->string('email')->unique(); $table->timestamps(); $table->softDeletes(); }); } public function down() { Schema::dropIfExists('auth_users'); } }; ``` #### 业务模块迁移 - 文件路径: `Modules/{ModuleName}/Database/migrations/` - 迁移文件命名: `{YYYY_MM_DD_HHMMSS}_{description}.php` - 表命名: `{module}_{table_names}` (模块名小写 + 下划线 + 表名复数,所有模块表都必须带模块名前缀) **表命名示例:** - Blog 模块: `blog_posts`, `blog_categories`, `blog_tags`, `blog_post_tag` - Shop 模块: `shop_products`, `shop_orders`, `shop_order_items` - Order 模块: `order_payments`, `order_shippings` ### 字段命名规范 - 使用蛇形命名: `user_id`, `created_at` - 布尔类型使用 `is_` 前缀: `is_active`, `is_deleted` - 主键统一使用 `id` ### 数据填充 #### 基础模块数据填充 - 文件路径: `database/seeders/` #### 业务模块数据填充 - 文件路径: `Modules/{ModuleName}/Database/seeders/` #### 菜单权限节点 Seed 规范 在 Seeder 文件中创建菜单权限节点时,需要遵循以下规范。 **数据库字段说明 (auth_permissions 表):** | 字段 | 类型 | 说明 | |------|------|------| | id | number | 权限ID | | title | string | 权限标题(用于菜单显示) | | name | string | 权限编码(唯一标识) | | type | string | 权限类型:menu(菜单)、api(接口)、button(按钮)、url(链接) | | parent_id | number | 父级ID,顶级菜单为 0 | | path | string | 路由路径(如 `/system/users`) | | component | string | 前端组件路径(如 `system/users/index`) | | meta | json | 元数据(包含 icon、hidden、keepAlive 等) | | sort | number | 排序 | | status | number | 状态:1启用 0禁用 | **菜单结构规范:** 1. **顶级菜单**(parent_id=0)不需要 component 值 - 顶级菜单作为分组容器,不需要指定组件路径 - 示例:系统管理菜单 2. **只有最后一级的菜单**才需要 component 值 - 如果菜单没有子菜单,则需要指定 component - 如果菜单有子菜单,则不需要指定 component 3. **非菜单类型**(如 button)不需要 component 值 - 按钮权限只用于权限控制,不涉及页面路由 4. **所有页面组件的菜单**在前端处理时都拉平挂载在 Layouts 框架组件下 - 前端会将菜单数据转换为路由,所有页面路由都会挂载到 Layout 布局下 - 不需要在前端维护嵌套的路由结构 ** Seeder 示例:** ```php '系统管理', 'name' => 'system', 'type' => 'menu', 'parent_id' => 0, 'path' => '/system', 'component' => null, // 顶级菜单不需要 component 'meta' => json_encode([ 'icon' => 'Setting', 'hidden' => false, 'hiddenBreadcrumb' => false, 'keepAlive' => false ]), 'sort' => 1, 'status' => 1, ], // 最后一级菜单(有 component) [ 'title' => '用户管理', 'name' => 'system.users', 'type' => 'menu', 'parent_id' => 0, 'path' => '/system/users', 'component' => 'system/users/index', // 最后一级菜单需要 component 'meta' => json_encode([ 'icon' => 'User', 'hidden' => false, 'hiddenBreadcrumb' => false, 'keepAlive' => true ]), 'sort' => 1, 'status' => 1, ], // 按钮权限(无 component) [ 'title' => '查看用户', 'name' => 'system.users.view', 'type' => 'button', 'parent_id' => 0, 'path' => 'admin.users.index', 'component' => null, // 非菜单类型不需要 component 'meta' => null, 'sort' => 1, 'status' => 1, ], // API 权限 [ 'title' => '获取用户列表', 'name' => 'system.users.list', 'type' => 'api', 'parent_id' => 0, 'path' => 'admin.users.index', 'component' => null, 'meta' => null, 'sort' => 1, 'status' => 1, ], ]; foreach ($permissions as $permission) { Permission::create($permission); } } ``` **重要说明:** - `title` 用于显示在菜单中的标题 - `name` 是权限的唯一标识编码,用于前端路由和权限验证 - `parent_id` 主要用于构建菜单树的层级关系(侧边栏显示) - `path` 用于菜单类型的路由路径,或 API 类型的接口路由名称 - `component` 值只需要在最后一级菜单(叶子节点)中设置 - 前端会根据 `type` 字段判断是否需要加载组件 ## 认证与授权 ### JWT 认证 使用 `tymon/jwt-auth` 实现 JWT 认证: ```php // 登录获取 token $token = auth('api')->attempt($credentials); // 使用 token 认证 $user = auth('api')->user(); // 刷新 token $newToken = auth('api')->refresh(); // 登出 auth('api')->logout(); ``` ### RBAC 权限控制 基于角色的访问控制 (Role-Based Access Control): - User (用户) - Role (角色) - Permission (权限) - 多对多关系设计 ## 常用命令 ### Laravel 命令 ```bash # 创建基础模块控制器 php artisan make:controller Auth/UserController # 创建基础模块模型 php artisan make:model Auth/User # 创建基础模块迁移 php artisan make:migration create_auth_users_table # 执行迁移(包括所有模块) php artisan migrate # 回滚迁移 php artisan migrate:rollback # 清除缓存 php artisan cache:clear php artisan config:clear php artisan route:clear ``` ### Laravel-S 命令 ```bash # 启动服务 php bin/laravels start # 停止服务 php bin/laravels stop # 重启服务 php bin/laravels restart # 重载服务(平滑重启) php bin/laravels reload # 查看状态 php bin/laravels status # 查看帮助 php bin/laravels help ``` ### Laravel Modules 命令 ```bash # 创建模块 php artisan module:make ModuleName # 列出所有模块 php artisan module:list # 启用模块 php artisan module:enable ModuleName # 禁用模块 php artisan module:disable ModuleName # 删除模块 php artisan module:delete ModuleName # 模块迁移 php artisan module:migrate ModuleName # 回滚模块迁移 php artisan module:migrate-rollback ModuleName # 刷新模块迁移 php artisan module:migrate-refresh ModuleName # 模块数据填充 php artisan module:seed ModuleName # 重新发布模块配置 php artisan vendor:publish --tag=modules-config ``` ## 代码质量 ### PSR 规范 遵循 PSR-4 自动加载规范和 PSR-12 编码规范。 ### 注释规范 - 类和方法添加 DocBlock 注释 - 复杂逻辑添加行内注释 **示例:** ```php /** * 用户服务类 * * @package App\Services\Auth */ class UserService { /** * 创建用户 * * @param array $data 用户数据 * @return User */ public function create(array $data): User { // 业务逻辑 } } ``` ## 模块开发规范 ### 1. 模块独立性 每个业务模块应保持独立,避免直接依赖其他业务模块: - 模块间通信通过接口或事件实现 - 避免跨模块直接调用服务类 - 使用 Laravel 事件系统实现模块间解耦 ### 2. 模块配置 每个业务模块应提供配置文件: ```php // Modules/Blog/config/blog.php return [ 'per_page' => 20, 'status' => [ 'draft' => 0, 'published' => 1, ], ]; ``` ### 3. 模块 README 每个业务模块应包含 README.md 文档,说明: - 模块功能描述 - API 接口列表 - 数据库表结构 - 依赖说明 - 使用示例 ### 4. 模块版本控制 使用 `module.json` 文件管理模块版本: ```json { "name": "Blog", "alias": "blog", "description": "Blog module", "keywords": [], "priority": 0, "providers": [ "Modules\\Blog\\App\\Providers\\BlogServiceProvider" ], "files": [] } ``` ## 异常处理 ### 自定义异常 创建自定义异常类处理业务异常: ```php code = $code; } public function render() { return response()->json([ 'code' => $this->code, 'message' => $this->message, 'data' => null ], $this->code); } } ``` ## 测试规范 ### 单元测试 ```bash # 创建测试 php artisan make:test UserTest # 运行测试 php artisan test ``` ### 模块测试 ```bash # 创建模块测试 php artisan module:test PostTest Blog # 运行所有测试 php artisan test ``` ## 部署注意事项 1. 生产环境关闭调试模式: `APP_ENV=production`, `APP_DEBUG=false` 2. 配置合适的 Worker 数量 3. 设置 `max_request` 防止内存泄漏 4. 配置日志轮转 5. 设置适当的超时时间 6. 确保所有模块的迁移都已执行 ## 安全规范 1. 所有用户输入必须经过验证 2. 敏感数据必须加密存储 3. 使用 CSRF 防护(API 除外) 4. 使用 HTTPS 传输 5. 定期更新依赖包 6. 不要在代码中硬编码密码或密钥 7. 模块间通信需进行权限验证 ## 性能优化 1. 使用 Redis 缓存热点数据 2. 使用队列处理耗时任务 3. 优化数据库查询,避免 N+1 问题 4. 使用 Eager Loading 5. 合理使用索引 6. 使用 Swoole 协程提高并发性能 7. 模块按需加载,禁用不使用的模块 ## Git 规范 ### 提交信息格式 ``` ():