---
url: /docs/3.0/server/model.md
---
# CatchAdmin 模型

> 基于 Laravel Eloquent 的增强模型基类和实用方法

在后台管理系统中，绝大多数业务逻辑都围绕数据模型展开。CatchAdmin 在 Laravel Eloquent 基础上进行了深度封装，提供了更适合后台开发的模型基类 `CatchModel`。

所有 CatchAdmin 的业务模型都继承自 `CatchModel`，这个基类集成了常用的后台操作方法，可以显著提升开发效率。

:::info 重要提醒
建议仔细阅读本文档，掌握 CatchModel 的特性将让你的开发效率倍增！
:::

## CatchModel 基类

CatchModel 是 CatchAdmin 所有业务模型的基类，通过多个 Trait 扩展了 Laravel Eloquent 的功能：

```php
abstract class CatchModel extends Model
{
    use BaseOperate, Trans, SoftDeletes, ScopeTrait;

    /**
     * unix timestamp
     *
     * @var string
     */
    protected $dateFormat = 'U';

    /**
     * paginate limit
     */
    protected $perPage = 10;

    /**
     * @var string[]
     */
    protected array $defaultCasts = [
        'created_at' => 'datetime:Y-m-d H:i:s',

        'updated_at' => 'datetime:Y-m-d H:i:s',
    ];

    protected array $defaultHidden = ['deleted_at'];

    public function __construct(array $attributes = [])
    {
        parent::__construct($attributes);

        $this->init();
    }

    /**
     * init
     */
    protected function init()
    {
        $this->makeHidden($this->defaultHidden);

        $this->mergeCasts($this->defaultCasts);
    }


    // 修改软删除的查询条件
    public static function bootSoftDeletes(): void
    {
        static::addGlobalScope(new SoftDelete());
    }
}
```

### 时间戳处理

CatchAdmin 所有数据表的 `created_at` 和 `updated_at` 字段都采用 Unix 时间戳（int 类型）存储。为了向前端返回可读的日期格式，CatchModel 通过 `defaultCasts` 属性进行自动转换：

```php
protected array $defaultCasts = [
    'created_at' => 'datetime:Y-m-d H:i:s',

    'updated_at' => 'datetime:Y-m-d H:i:s',
];
```

> 这里有人肯定会有疑问？为什么要非要加一个 `defaultCasts` 属性呢？为什么不直接用 `casts`？

:::tip 设计考虑
使用 `defaultCasts` 而非 `casts` 属性的原因：

1. **避免覆盖冲突**：所有模型都继承自 CatchModel，使用 `casts` 可能被子类覆盖
2. **通用性保证**：日期转换几乎每个模型都需要，独立属性确保功能稳定
3. **一致性维护**：`defaultHidden` 属性也遵循同样的设计理念
   :::

## 软删除

### 软删除机制

CatchAdmin 的软删除设计与 Laravel 默认实现不同：软删除字段 `deleted_at` 的默认值是 **0**（而非 null）。因此需要自定义软删除的查询条件：

```php
class SoftDelete extends SoftDeletingScope
{
    public function apply(Builder $builder, Model $model)
    {
        $builder->where($model->getQualifiedDeletedAtColumn(), '=', 0);
    }
}
```

## 取消软删

### 取消软删除

某些业务场景不需要软删除功能，比如操作日志等记录型数据。此时可以继承 Laravel 原生的 `Model` 类，同时引入 CatchAdmin 的功能 Trait：

```php
namespace Modules\User\Models;

use Catch\CatchAdmin;
// 添加以下三个 trait 操作
use Catch\Traits\DB\BaseOperate; // 基本操作
use Catch\Traits\DB\ScopeTrait; // scope trait
use Catch\Traits\DB\Trans; // 事务操作
use Illuminate\Database\Eloquent\Model;

class LogOperate extends Model
{
    use BaseOperate, Trans, ScopeTrait;
}
```

## 属性

### 扩展属性

CatchModel 新增了多个实用属性，简化常见的后台开发需求：

```php

    // 树状结构的父级字段，建议使用默认值
    // CatchAdmin 的树组件统一使用此字段
    protected string $parentIdColumn = 'parent_id';

    // 排序字段，默认使用 sort
    protected string $sortField = 'sort';

    // 排序规则
    protected bool $sortDesc = true;

    // 列表的数据返回是否以树状结构返回
    protected bool $asTree = false;

    // 列表查询的默认字段
    protected array $fields = [];

    // 列表是否是分页
    // 默认分页
    protected bool $isPaginate = true;

    // 创建和更新数据提交的字段
    // form 字段
    protected array $form = [];

    // 表单关联关系配置
    // 示例：用户与角色的多对多关系
    // 在 User 模型中设置：['roles']
    // 对应模型中的 roles() 关联方法
    protected array $formRelations = [];
```

## 模型方法

CatchModel 提供了丰富的便捷方法，覆盖后台开发的常见场景。

## 列表查询

```php
public function getList(): miexed
```

### 支持自定义查询

`getList()` 方法默认针对单表查询。如需复杂查询（如 join、with 关联等），可以使用查询钩子进行自定义：

```php
// 示例：添加排序条件
$model->setBeforeGetList(function ($query) {
    return $query->orderByDesc('sort');
})->getList();
```

```php
// 示例：联表查询
$model->setBeforeGetList(function ($query) {
    return $query->join('some_table', 'condition');
})->getList();
```

```php
// 示例：预加载关联关系
$model->setBeforeGetList(function ($query) {
    return $query->with('someRelations');
})->getList();
```

## 数据保存

### 单条保存

```php
public function storeBy(array $data): bool
```

用于保存单条记录，支持表单关联关系自动处理。

### 批量保存

```php
public function createBy(array $data): mixed
```

支持批量插入数据，适用于导入、初始化等场景。

:::info 方法区别

* `storeBy`：适合表单提交的单条数据保存
* `createBy`：适合批量数据插入，性能更好
  :::

## 更新数据

```php
public function updateBy($id, array $data): mixed
```

## 查询数据

```php
public function firstBy($value, $field = null, array $columns = ['*']): ?Model
```

`$field` 参数默认为 `id`，支持按任意字段查询。

## 删除数据

```php
public function deleteBy($id, bool $force = false): ?bool
```

默认按 `id` 进行软删除，`$force` 参数为 `true` 时执行物理删除。

## 状态切换

```php
public function toggleBy($id, string $field = 'status'): bool
```

常用于启用/禁用功能，通过 ID 切换指定字段的状态（0/1）。

## 处理树状数据的下级数据

```php
public function updateChildren(mixed $parentId, string $field, mixed $value): void
```

## 字段别名

```php
public function aliasField(string|array $fields): string|array
```

## 设置 ceator\_id

```php
public function setCreatorId()
```

## 创建人字段

CatchAdmin 默认自动填充创建人字段 `creator_id`。如需取消此功能：

```php
$model->fillCreatorId(false)->storeBy($data);
```

## 获取创建人

```php
public function scopeCreator();
```

这是一个查询作用域，可以链式调用：

```php
Model::select('*')->creator()->get();
```

**注意**：使用前请确保数据表包含 `creator_id` 字段。

## 模糊查询

```php
public function whereLike($field, $value)
```

## 快速查询

```php
public function quickSearch(array $params = [])
```

通过配置模型的 `searchable` 属性，自动根据请求参数生成查询条件：

```php
protected array $searchable = [
    'status' => '=',

    'nickname' => 'like'
]
```

配置后，系统会自动生成相应的查询条件，实现动态搜索：

```php
Model::select('*')
    ->where('status', $request->get('status'))
    ->whereLike('nickname', $request->get('nickname'))
    ->get();
```

## 事务操作

CatchModel 集成了事务操作，无需再引入 DB 门面：

```php
// 传统方式
DB::beginTransaction();

// CatchModel 方式
$this->beginTransaction();
```

支持所有 Laravel 事务方法：`beginTransaction()`、`commit()`、`rollback()`。
