457 lines
13 KiB
Markdown
457 lines
13 KiB
Markdown
# 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
|
||
```
|
||
|
||
## 模板文件
|
||
|
||
### 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. **维护成本降低**:统一的代码结构和规范 |