study-api-v2/docs/CRUD代码生成模板.md
hx a621de91ff feat(system): 添加系统菜单、角色菜单关联和用户角色关联功能- 新增系统菜单模型、控制器、请求验证和业务逻辑
- 新增角色菜单关联模型、控制器、请求验证和业务逻辑
- 新增用户角色关联模型、控制器、请求验证和业务逻辑
- 更新系统角色模型,增加与用户和菜单的关联
- 更新用户模型,增加与角色的关联和相关方法
- 在路由文件中添加新功能的路由定义
2025-07-15 01:14:15 +08:00

474 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Laravel CRUD 代码生成模板(优化版)
## 架构说明
### 分层架构
- **BaseModel.php**提供通用的权限控制tenant_id 自动过滤)、软删除、时间戳等基础功能
- **BaseService.php**:提供标准的 CRUD 操作,统一事务处理和异常处理
- **BaseController.php**提供统一的响应格式Success、SuccessPage、Field和参数获取方法
- **Controllers**:只负责参数验证和调用服务层,无需关心权限控制和异常处理
### 权限控制机制
- **查询时**BaseModel 的全局作用域自动过滤当前用户的 tenant_id 数据
- **创建时**BaseModel 的 creating 钩子自动设置当前用户的 tenant_id
- **更新/删除时**BaseService 在操作前验证记录的 tenant_id 权限
### 目录结构规范
```
app/
├── Models/
│ └── [模块名]/
│ └── [表名Model].php
├── Services/
│ └── [模块名]/
│ └── [表名Service].php
├── Http/
│ ├── Controllers/
│ │ └── Admin/
│ │ └── [模块名]/
│ │ └── [表名Controller].php
│ └── Requests/
│ └── Admin/
│ └── [模块名]/
│ └── [表名Request].php
└── routes/
└── admin/
└── [模块名]_route.php
```
### 模型命名规范
- **模型名必须与数据库表名保持一致的大驼峰格式**
- 例如:`system_users` 表 → `SystemUsers` 模型
- 例如:`system_role` 表 → `SystemRole` 模型
- 例如:`user_profile` 表 → `UserProfile` 模型
- **不要使用简化名称**,严格按照表名转换大驼峰
## 模板文件
### 1. 模型文件模板
**文件路径**`app/Models/[模块名]/[表名].php`
```php
<?php
namespace App\Models\[模块名];
use App\Models\BaseModel;
/**
* [中文名称]模型
*/
class [表名] extends BaseModel
{
protected $table = '[数据库表名]';
protected $fillable = [
'[字段1]',
'[字段2]',
// ... 其他可填充字段
];
protected $casts = [
'created_at' => 'datetime',
'updated_at' => 'datetime',
];
// 如果有特殊的查询作用域,可以添加
// public function scopeActive($query)
// {
// return $query->where('status', 1);
// }
// 如果有关联关系,可以添加
// public function relatedModel()
// {
// return $this->belongsTo(RelatedModel::class);
// }
}
```
### 2. 服务文件模板
**文件路径**`app/Services/[模块名]/[表名Service].php`
```php
<?php
namespace App\Services\[模块名];
use App\Models\[模块名]\[表名];
use App\Services\BaseService;
use Illuminate\Pagination\LengthAwarePaginator;
/**
* [中文名称]服务类
*/
class [表名Service] extends BaseService
{
protected string $modelClass = [表名]::class;
/**
* 获取[中文名称]列表
*/
public function getList(array $params): LengthAwarePaginator
{
$query = [表名]::query();
// 搜索条件
if (!empty($params['keyword'])) {
$query->where(function ($q) use ($params) {
$q->where('name', 'like', '%' . $params['keyword'] . '%')
->orWhere('code', 'like', '%' . $params['keyword'] . '%');
});
}
// 状态筛选
if (isset($params['status'])) {
$query->where('status', $params['status']);
}
// 排序
$query->orderBy('sort_order', 'asc')
->orderBy('id', 'desc');
return $query->paginate($params['page_size'] ?? 15);
}
/**
* 获取简单列表(用于下拉选择等)
*/
public function getSimpleList(): array
{
return [表名]::select('id', 'name')
->where('status', 1)
->orderBy('sort_order', 'asc')
->get()
->toArray();
}
// 如果有特殊业务逻辑,可以重写父类方法
// protected function beforeCreate(array &$data): void
// {
// // 创建前的特殊处理
// }
// protected function afterCreate($model, array $data): void
// {
// // 创建后的特殊处理
// }
}
```
### 3. 控制器文件模板
**文件路径**`app/Http/Controllers/Admin/[模块名]/[表名Controller].php`
```php
<?php
namespace App\Http\Controllers\Admin\[模块名];
use App\Http\Controllers\BaseController;
use App\Http\Requests\Admin\[模块名]\[表名Request];
use App\Services\[模块名]\[表名Service];
use Illuminate\Http\JsonResponse;
/**
* [中文名称]控制器
*/
class [表名Controller] extends BaseController
{
public function __construct(
private [表名Service] $[表名变量]Service
) {}
/**
* 获取[中文名称]列表
*/
public function list([表名Request] $request): JsonResponse
{
$params = $request->validated();
$result = $this->[表名变量]Service->getList($params);
return $this->SuccessPage($result->items(), $result->total());
}
/**
* 获取简单列表
*/
public function simpleList(): JsonResponse
{
$result = $this->[表名变量]Service->getSimpleList();
return $this->Success($result);
}
/**
* 获取[中文名称]详情
*/
public function detail([表名Request] $request): JsonResponse
{
$params = $request->validated();
$result = $this->[表名变量]Service->detail($params['id']);
return $this->Success($result);
}
/**
* 创建[中文名称]
*/
public function create([表名Request] $request): JsonResponse
{
$data = $request->validated();
$result = $this->[表名变量]Service->create($data);
return $this->Success($result);
}
/**
* 更新[中文名称]
*/
public function update([表名Request] $request): JsonResponse
{
$params = $request->validated();
$result = $this->[表名变量]Service->update($params['id'], $params);
return $this->Success($result);
}
/**
* 删除[中文名称]
*/
public function delete([表名Request] $request): JsonResponse
{
$params = $request->validated();
$this->[表名变量]Service->delete($params['id']);
return $this->Success();
}
/**
* 批量删除[中文名称]
*/
public function batchDelete([表名Request] $request): JsonResponse
{
$params = $request->validated();
$this->[表名变量]Service->batchDelete($params['ids']);
return $this->Success();
}
}
```
### 4. 验证文件模板
**文件路径**`app/Http/Requests/Admin/[模块名]/[表名Request].php`
```php
<?php
namespace App\Http\Requests\Admin\[模块名];
use App\Http\Requests\BaseRequest;
/**
* [中文名称]请求验证
*/
class [表名Request] extends BaseRequest
{
/**
* 获取验证规则
*/
public function rules(): array
{
$action = $this->route()->getActionMethod();
return match($action) {
'list' => $this->listRules(),
'detail' => $this->detailRules(),
'create' => $this->createRules(),
'update' => $this->updateRules(),
'delete' => $this->deleteRules(),
'batchDelete' => $this->batchDeleteRules(),
'simpleList' => [],
default => []
};
}
/**
* 列表查询验证规则
*/
private function listRules(): array
{
return array_merge($this->getPaginationRules(), [
'keyword' => ['sometimes', 'string', 'max:50'],
'status' => ['sometimes', 'integer', 'in:0,1'],
]);
}
/**
* 详情查询验证规则
*/
private function detailRules(): array
{
return [
'id' => ['required', 'integer', 'exists:[数据库表名],id'],
];
}
/**
* 创建验证规则
*/
private function createRules(): array
{
return [
'name' => ['required', 'string', 'max:100'],
'code' => ['required', 'string', 'max:50', 'unique:[数据库表名],code'],
'status' => ['sometimes', 'integer', 'in:0,1'],
'sort_order' => ['sometimes', 'integer', 'min:0'],
'remark' => ['sometimes', 'string', 'max:200'],
];
}
/**
* 更新验证规则
*/
private function updateRules(): array
{
return [
'id' => ['required', 'integer', 'exists:[数据库表名],id'],
'name' => ['required', 'string', 'max:100'],
'code' => ['required', 'string', 'max:50', 'unique:[数据库表名],code,' . $this->input('id')],
'status' => ['sometimes', 'integer', 'in:0,1'],
'sort_order' => ['sometimes', 'integer', 'min:0'],
'remark' => ['sometimes', 'string', 'max:200'],
];
}
/**
* 删除验证规则
*/
private function deleteRules(): array
{
return [
'id' => ['required', 'integer', 'exists:[数据库表名],id'],
];
}
/**
* 批量删除验证规则
*/
private function batchDeleteRules(): array
{
return [
'ids' => ['required', 'array', 'min:1'],
'ids.*' => ['integer', 'exists:[数据库表名],id'],
];
}
/**
* 获取验证错误消息
*/
public function messages(): array
{
return [
'name.required' => '[中文名称]名称不能为空',
'name.max' => '[中文名称]名称不能超过100个字符',
'code.required' => '[中文名称]编码不能为空',
'code.unique' => '[中文名称]编码已存在',
'status.in' => '[中文名称]状态值无效',
'ids.required' => '请选择要删除的[中文名称]',
'ids.min' => '至少选择一条记录进行删除',
];
}
}
```
### 5. 路由文件模板
**文件路径**`routes/admin/[模块名]_route.php`
```php
<?php
use Illuminate\Support\Facades\Route;
/** -------------------------- [中文名称] ----------------------- */
Route::middleware("admin")->group(function () {
// 获取[中文名称]详情
Route::match(['get', 'post'], "[路由前缀]/detail", [App\Http\Controllers\Admin\[模块名]\[表名Controller]::class, 'detail']);
// 创建[中文名称]
Route::match(['get', 'post'], "[路由前缀]/create", [App\Http\Controllers\Admin\[模块名]\[表名Controller]::class, 'create']);
// 更新[中文名称]
Route::match(['put', 'post'], "[路由前缀]/update", [App\Http\Controllers\Admin\[模块名]\[表名Controller]::class, 'update']);
// 删除[中文名称]
Route::match(['delete', 'post'], "[路由前缀]/delete", [App\Http\Controllers\Admin\[模块名]\[表名Controller]::class, 'delete']);
// 获取[中文名称]列表
Route::match(['get', 'post'], "[路由前缀]/list", [App\Http\Controllers\Admin\[模块名]\[表名Controller]::class, 'list']);
// 获取简单列表
Route::match(['get', 'post'], "[路由前缀]/simple/list", [App\Http\Controllers\Admin\[模块名]\[表名Controller]::class, 'simpleList']);
// 批量删除[中文名称]
Route::match(['delete', 'post'], "[路由前缀]/batch/delete", [App\Http\Controllers\Admin\[模块名]\[表名Controller]::class, 'batchDelete']);
});
```
## 使用示例
假设我们要为`school_class`表生成 CRUD 代码:
### 替换变量说明
- `[模块名]``Schools`
- `[表名]``SchoolClass`
- `[表名变量]``schoolClass`
- `[数据库表名]``school_class`
- `[中文名称]``班级`
- `[路由前缀]``school/class`
### 生成的文件结构
```
app/
├── Models/Schools/SchoolClass.php
├── Services/Schools/SchoolClassService.php
├── Http/
│ ├── Controllers/Admin/Schools/SchoolClassController.php
│ └── Requests/Admin/Schools/SchoolClassRequest.php
└── routes/admin/schools_route.php
```
### 控制器方法命名规范
- `list()` - 获取列表(替代 index
- `detail()` - 获取详情(替代 show
- `create()` - 创建(替代 store
- `update()` - 更新
- `delete()` - 删除(替代 destroy
- `batchDelete()` - 批量删除
- `simpleList()` - 获取简单列表
### 验证规则命名规范
验证方法根据控制器方法名自动匹配:
- `listRules()` - 列表查询验证
- `detailRules()` - 详情查询验证
- `createRules()` - 创建验证
- `updateRules()` - 更新验证
- `deleteRules()` - 删除验证
- `batchDeleteRules()` - 批量删除验证
## 核心优势
1. **代码量减少 60%以上**:通过 BaseModel、BaseService 提供通用功能
2. **权限控制自动化**tenant_id 完全由框架层自动处理
3. **异常处理统一化**:控制器无需 try-catch全局异常处理器统一处理
4. **命名更加直观**:使用功能性命名而非传统 RESTful 命名
5. **开发效率极高**:新模块只需实现特殊业务逻辑
6. **维护成本降低**:统一的代码结构和规范