151 lines
4.6 KiB
Markdown
151 lines
4.6 KiB
Markdown
# 3.3 模型层开发
|
||
|
||
:::tip 概述
|
||
模型层负责定义数据库表的映射关系。通过组合两个模型 Trait(`SoftDeletesByFlag`、`HasAuditColumns`),自动获得软删除和审计字段能力。
|
||
:::
|
||
|
||
## 模型文件位置
|
||
|
||
```text
|
||
app/Models/Example.php
|
||
```
|
||
|
||
## 完整代码(来自项目实际代码)
|
||
|
||
```php
|
||
<?php
|
||
|
||
namespace App\Models;
|
||
|
||
use App\Models\Concerns\HasAuditColumns;
|
||
use App\Models\Concerns\SoftDeletesByFlag;
|
||
use Illuminate\Database\Eloquent\Model;
|
||
|
||
/**
|
||
* 案例演示模型
|
||
*
|
||
* 对应数据表 example,继承 Eloquent Model 获得通用模型能力。
|
||
*
|
||
* 说明:
|
||
* - 通过 HasAuditColumns 自动维护审计字段(如 created_by、updated_by 等)。
|
||
* - 通过 SoftDeletesByFlag 实现基于标志位的软删除(如 is_deleted 字段)。
|
||
* - type 类型:1=类型1,2=类型2,3=类型3,4=类型4。
|
||
* - status 状态:1=在用,2=停用。
|
||
* - 本模型通常作为开发示例/模板使用,不承载具体业务逻辑。
|
||
*/
|
||
class Example extends Model
|
||
{
|
||
use HasAuditColumns, SoftDeletesByFlag;
|
||
|
||
/**
|
||
* 数据表名
|
||
*
|
||
* 显式指定表名为 example,覆盖默认的类名推导规则。
|
||
*
|
||
* @var string
|
||
*/
|
||
protected $table = 'example';
|
||
|
||
/**
|
||
* 允许批量赋值的字段列表
|
||
*
|
||
* 白名单中的字段可通过 create()、update()、fill() 等方式批量赋值。
|
||
*
|
||
* @var array<int, string>
|
||
*/
|
||
protected $fillable = [
|
||
'name', // 名称
|
||
'avatar', // 头像/图片地址
|
||
'type', // 类型:1=类型1,2=类型2,3=类型3,4=类型4
|
||
'status', // 状态:1=在用,2=停用
|
||
'sort', // 排序值,数值越小越靠前(视业务而定)
|
||
];
|
||
}
|
||
```
|
||
|
||
:::tip 表名与前缀
|
||
`$table = 'example'` 不含前缀,实际查询时由 `DB_PREFIX=laravel_` 自动拼接为 `laravel_example`。
|
||
:::
|
||
|
||
## 组合 Trait 后获得的能力
|
||
|
||
| Trait | 能力 | 代码示例 |
|
||
|------|------|----------|
|
||
| `SoftDeletesByFlag` | 注册 `SoftDeleteFlagScope` 全局范围,查询自动过滤 `is_delete=1` | `Example::query()` 自动排除已删除 |
|
||
| `SoftDeletesByFlag` | 标记删除单条 | `$model->softDelete();`(置 `is_delete=1`) |
|
||
| `SoftDeletesByFlag` | 批量标记删除 | `Example::batchSoftDelete([1,2,3]);` |
|
||
| `HasAuditColumns` | `creating` 事件自动填充 `create_user`(当前登录人)和 `create_time` | `Example::create([...])` 时自动填充 |
|
||
| `HasAuditColumns` | `updating` 事件自动填充 `update_user`、`update_time`(每次强制覆盖) | `$model->update([...])` 时自动填充 |
|
||
|
||
:::tip 审计字段说明
|
||
`create_user` 取自 `Auth::username()`(当前登录用户);`create_*` 采用 `??` 逻辑——已显式赋值则保留原值,`update_*` 每次强制覆盖。表结构不含 Laravel 默认的 `created_at` / `updated_at`。
|
||
:::
|
||
|
||
## 查询已删除数据
|
||
|
||
```php
|
||
// 查询单条(包括已删除)—— 移除全局软删除范围
|
||
$example = Example::withoutGlobalScope(SoftDeleteFlagScope::class)->find($id);
|
||
|
||
// 查询所有(包括已删除)
|
||
$all = Example::withoutGlobalScope(SoftDeleteFlagScope::class)->get();
|
||
|
||
// 恢复(软删除字段归零)
|
||
$example->update(['is_delete' => 0]);
|
||
```
|
||
|
||
## 简单模型 vs 复杂模型
|
||
|
||
:::tip 模型层职责
|
||
模型层只负责表映射和关联关系,不包含业务逻辑。所有查询条件、排序、唯一性校验等都由 Service 层配置。
|
||
:::
|
||
|
||
### 简单模型(如 Example)
|
||
|
||
只需声明表名与批量赋值白名单,所有逻辑由 Service 层配置:
|
||
|
||
```php
|
||
class Example extends Model
|
||
{
|
||
use HasAuditColumns, SoftDeletesByFlag;
|
||
|
||
protected $table = 'example';
|
||
protected $fillable = ['name', 'avatar', 'type', 'status', 'sort'];
|
||
}
|
||
```
|
||
|
||
### 复杂模型(如 Role)
|
||
|
||
包含关联关系(以项目实际代码为例):
|
||
|
||
```php
|
||
class Role extends Model
|
||
{
|
||
use HasAuditColumns, SoftDeletesByFlag;
|
||
|
||
protected $table = 'role';
|
||
protected $fillable = [...];
|
||
|
||
/**
|
||
* 角色关联的菜单(多对多,经 role_menu 中间表)
|
||
*/
|
||
public function menus(): BelongsToMany
|
||
{
|
||
return $this->belongsToMany(Menu::class, 'role_menu', 'role_id', 'menu_id')
|
||
->wherePivot('is_delete', 0);
|
||
}
|
||
}
|
||
```
|
||
|
||
## 模型相关文件
|
||
|
||
```text
|
||
app/Models/
|
||
├── Concerns/
|
||
│ ├── SoftDeletesByFlag.php # is_delete 软删除(注册全局 Scope + softDelete 方法)
|
||
│ ├── SoftDeleteFlagScope.php # 全局查询范围(WHERE is_delete = 0)
|
||
│ └── HasAuditColumns.php # 审计字段(creating/updating 事件填充)
|
||
├── Example.php # 案例模型
|
||
└── ...
|
||
```
|