26 KiB
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: 关系型数据库
模块化架构
模块分类
项目分为两类模块:
-
基础模块 (Base Modules)
- Auth: 认证授权模块(用户、角色、权限)
- System: 系统配置模块(配置、日志、字典)
- 特点:不使用
nwidart/laravel-modules扩展,直接在 Laravel 应用结构中开发 - 位置:
app/目录下
-
业务模块 (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
namespace App\Http\Controllers\Auth;
use Illuminate\Http\Request;
use App\Services\Auth\UserService;
class User extends Controller
{
protected $userService;
public function __construct(UserService $userService)
{
$this->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
namespace Modules\Blog\App\Http\Controllers\Admin;
use Illuminate\Http\Request;
use Modules\Blog\App\Services\PostService;
class Post extends Controller
{
protected $postService;
public function __construct(PostService $postService)
{
$this->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
namespace Modules\Blog\App\Http\Controllers\Api;
use Illuminate\Http\Request;
use Modules\Blog\App\Services\PostService;
class Post extends Controller
{
protected $postService;
public function __construct(PostService $postService)
{
$this->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
namespace App\Services\Auth;
use App\Models\Auth\User;
use Illuminate\Support\Facades\Hash;
class UserService
{
public function create(array $data): User
{
$data['password'] = Hash::make($data['password']);
return User::create($data);
}
public function getById(int $id): ?User
{
return User::find($id);
}
}
业务模块服务
命名规范:
- 文件路径:
Modules/{ModuleName}/App/Services/{Name}Service.php - 类名:
{Name}Service - 命名空间:
Modules\{ModuleName}\App\Services
示例:
<?php
namespace Modules\Blog\App\Services;
use Modules\Blog\App\Models\Post;
class PostService
{
public function create(array $data): Post
{
return Post::create($data);
}
public function getById(int $id): ?Post
{
return Post::find($id);
}
}
3. 模型层 (Models)
基础模块模型
命名规范:
- 文件路径:
app/Models/{Module}/{Name}.php - 类名:
{Name}(单数形式) - 命名空间:
App\Models\{Module} - 数据表:
{module}_{names}(复数形式,带模块前缀)
示例:
<?php
namespace App\Models\Auth;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class Role extends Model
{
protected $table = 'auth_roles';
protected $fillable = ['name', 'description'];
public function permissions(): BelongsToMany
{
return $this->belongsToMany(Permission::class, 'auth_role_permission');
}
}
业务模块模型
命名规范:
- 文件路径:
Modules/{ModuleName}/App/Models/{Name}.php - 类名:
{Name}(单数形式) - 命名空间:
Modules\{ModuleName}\App\Models - 数据表:
{module}_{names}(复数形式,带模块前缀)
示例:
<?php
namespace Modules\Blog\App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $table = 'blog_posts';
protected $fillable = ['title', 'content', 'status'];
}
4. 中间件 (Middleware)
常用中间件:
AdminAuth: 后台管理认证api.throttle: API 请求频率限制
5. API 路由
基础模块路由
基础模块路由定义在 routes/ 目录下,通过 bootstrap/app.php 进行配置:
routes/admin.php: 后台管理路由,自动添加/admin前缀和admin.路由名称前缀routes/api.php: 公共 API 路由,自动添加/api前缀routes/web.php: Web 路由routes/console.php: 命令行路由
路由配置 (bootstrap/app.php):
<?php
return Application::configure(basePath: dirname(__DIR__))
->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
// routes/admin.php - 后台管理路由
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Auth\User;
Route::middleware(['admin.auth'])->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
use Illuminate\Support\Facades\Route;
use Modules\Blog\App\Http\Controllers\Admin\Post;
Route::middleware(['admin.auth'])->group(function () {
Route::apiResource('blog/posts', Post::class);
});
路由访问路径:/admin/{module}/{resource}
2. 用户端 API 路由 (Routes/api.php)
文件路径:Modules/{ModuleName}/Routes/api.php
<?php
use Illuminate\Support\Facades\Route;
use Modules\Blog\App\Http\Controllers\Api\Post;
Route::middleware(['auth:api'])->group(function () {
Route::apiResource('blog/posts', Post::class);
});
路由访问路径:/api/{module}/{resource}
6. 模块创建命令
使用 nwidart/laravel-modules 创建新业务模块:
# 创建模块
php artisan module:make ModuleName
# 创建带有资源的模块
php artisan module:make ModuleName --resource
# 创建多个模块
php artisan module:make Blog Shop Order
7. 模块组件创建命令
# 在指定模块中创建后台管理控制器
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 响应规范
统一响应格式
成功响应:
{
"code": 200,
"message": "success",
"data": {}
}
错误响应:
{
"code": 400,
"message": "错误信息",
"data": null
}
分页响应:
{
"code": 200,
"message": "success",
"data": {
"list": [],
"total": 100,
"page": 1,
"page_size": 20
}
}
树形响应:
{
"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 是长生命周期运行,需注意以下几点:
避免使用静态变量:
// ❌ 错误
public function handle()
{
static $counter = 0; // 会累积,不会重置
}
// ✅ 正确
public function handle()
{
$counter = 0; // 每次请求重新初始化
}
避免使用全局变量:
- 不要依赖
$_GET,$_POST等超全局变量 - 使用 Laravel 的
Request对象获取请求数据
2. 连接池管理
数据库、Redis 等连接需要正确管理,避免连接泄漏。
配置连接池: 在 config/laravels.php 中配置:
'swoole' => [
'enable_coroutine' => true,
'worker_num' => 4,
'max_request' => 5000,
'max_request_grace' => 500,
]
3. 热重载机制
开发环境可以使用文件监控实现热重载:
# 使用 bin/laravels reload
php bin/laravels reload
# 或使用文件监控
bin/fswatch # Linux/Mac
bin/inotify # Linux
4. 定时器
使用 Swoole 定时器时,要确保定时器在合适的时机清除:
\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
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up()
{
Schema::create('auth_users', function (Blueprint $table) {
$table->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禁用 |
菜单结构规范:
-
顶级菜单(parent_id=0)不需要 component 值
- 顶级菜单作为分组容器,不需要指定组件路径
- 示例:系统管理菜单
-
只有最后一级的菜单才需要 component 值
- 如果菜单没有子菜单,则需要指定 component
- 如果菜单有子菜单,则不需要指定 component
-
非菜单类型(如 button)不需要 component 值
- 按钮权限只用于权限控制,不涉及页面路由
-
所有页面组件的菜单在前端处理时都拉平挂载在 Layouts 框架组件下
- 前端会将菜单数据转换为路由,所有页面路由都会挂载到 Layout 布局下
- 不需要在前端维护嵌套的路由结构
** Seeder 示例:**
<?php
private function createPermissions(): void
{
$permissions = [
// 顶级菜单(无 component)
[
'title' => '系统管理',
'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 认证:
// 登录获取 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 命令
# 创建基础模块控制器
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 命令
# 启动服务
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 命令
# 创建模块
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 注释
- 复杂逻辑添加行内注释
示例:
/**
* 用户服务类
*
* @package App\Services\Auth
*/
class UserService
{
/**
* 创建用户
*
* @param array $data 用户数据
* @return User
*/
public function create(array $data): User
{
// 业务逻辑
}
}
模块开发规范
1. 模块独立性
每个业务模块应保持独立,避免直接依赖其他业务模块:
- 模块间通信通过接口或事件实现
- 避免跨模块直接调用服务类
- 使用 Laravel 事件系统实现模块间解耦
2. 模块配置
每个业务模块应提供配置文件:
// Modules/Blog/config/blog.php
return [
'per_page' => 20,
'status' => [
'draft' => 0,
'published' => 1,
],
];
3. 模块 README
每个业务模块应包含 README.md 文档,说明:
- 模块功能描述
- API 接口列表
- 数据库表结构
- 依赖说明
- 使用示例
4. 模块版本控制
使用 module.json 文件管理模块版本:
{
"name": "Blog",
"alias": "blog",
"description": "Blog module",
"keywords": [],
"priority": 0,
"providers": [
"Modules\\Blog\\App\\Providers\\BlogServiceProvider"
],
"files": []
}
异常处理
自定义异常
创建自定义异常类处理业务异常:
<?php
namespace App\Exceptions;
use Exception;
class BusinessException extends Exception
{
protected $code;
public function __construct(string $message, int $code = 400)
{
parent::__construct($message, $code);
$this->code = $code;
}
public function render()
{
return response()->json([
'code' => $this->code,
'message' => $this->message,
'data' => null
], $this->code);
}
}
测试规范
单元测试
# 创建测试
php artisan make:test UserTest
# 运行测试
php artisan test
模块测试
# 创建模块测试
php artisan module:test PostTest Blog
# 运行所有测试
php artisan test
部署注意事项
- 生产环境关闭调试模式:
APP_ENV=production,APP_DEBUG=false - 配置合适的 Worker 数量
- 设置
max_request防止内存泄漏 - 配置日志轮转
- 设置适当的超时时间
- 确保所有模块的迁移都已执行
安全规范
- 所有用户输入必须经过验证
- 敏感数据必须加密存储
- 使用 CSRF 防护(API 除外)
- 使用 HTTPS 传输
- 定期更新依赖包
- 不要在代码中硬编码密码或密钥
- 模块间通信需进行权限验证
性能优化
- 使用 Redis 缓存热点数据
- 使用队列处理耗时任务
- 优化数据库查询,避免 N+1 问题
- 使用 Eager Loading
- 合理使用索引
- 使用 Swoole 协程提高并发性能
- 模块按需加载,禁用不使用的模块
Git 规范
提交信息格式
<type>(<scope>): <subject>
<body>
<footer>
Type 类型:
feat: 新功能fix: 修复docs: 文档style: 格式refactor: 重构test: 测试chore: 构建/工具
Scope 示例:
auth: 认证模块system: 系统模块blog: 博客业务模块shop: 商城业务模块
示例:
feat(auth): 添加用户登录功能
- 实现 JWT 认证
- 添加登录接口
- 完善权限验证
Closes #123