Skip to content

CatchModel 模型介绍

在后台项目开发中,大部分业务逻辑都与数据模型操作和数据库交互相关。为了简化开发流程并提供统一的数据操作接口,CatchAdmin 框架提供了功能强大的模型基类 CatchModel。所有业务模型都继承自 CatchModel,从而获得丰富的数据操作功能和内置特性。

重要提示

建议仔细阅读本文档,全面掌握 CatchModel 的数据操作功能将显著提升开发效率

CatchModel 核心类

CatchModelCatchAdmin 框架的核心模型基类,基于 Laravel Eloquent ORM 进行扩展,继承自 Laravel 的 Model 类,并集成了多个高级功能特性:

php
abstract class CatchModel extends Model
{
    use BaseOperate;
    use DateformatTrait;
    use ScopeTrait;
    use SoftDeletes;
    use Trans;
    use WithAttributes;

    /**
     * 使用 Unix 时间戳格式
     * @var string
     */
    protected $dateFormat = 'U';

    /**
     * 默认分页数量
     */
    protected $perPage = 10;

    /**
     * 关闭 Laravel 自动时间戳管理
     * @var bool
     */
    public $timestamps = false;

    /**
     * 默认类型转换配置
     * @var array
     */
    protected array $defaultCasts = [];

    /**
     * 默认隐藏字段
     * @var array
     */
    protected array $defaultHidden = ['deleted_at'];

    public function __construct(array $attributes = [])
    {
        parent::__construct($attributes);
        $this->init();
    }

    /**
     * 初始化模型配置
     */
    protected function init(): void
    {
        $this->makeHidden($this->defaultHidden);
        $this->mergeCasts(array_merge(
            $this->defaultCasts,
            $this->dateFormatCasts(),
            [$this->getDeletedAtColumn() => 'integer'],
        ));
    }

    /**
     * 自定义软删除启动方法
     */
    public static function bootSoftDeletes(): void
    {
        static::addGlobalScope(new SoftDelete());
    }

    /**
     * 覆盖恢复方法,使用自定义的软删除逻辑
     */
    public function restore(): bool
    {
        if ($this->fireModelEvent('restoring') === false) {
            return false;
        }

        $this->{$this->getDeletedAtColumn()} = 0;
        $this->exists = true;
        $result = $this->save();
        $this->fireModelEvent('restored', false);

        return $result;
    }

    protected function runSoftDelete()
    {
        $query = $this->setKeysForSaveQuery($this->newModelQuery());
        $timestamp = (int) $this->fromDateTime($this->freshTimestamp());

        $columns = [$this->getDeletedAtColumn() => $timestamp];

        $this->{$this->getDeletedAtColumn()} = $timestamp;

        if ($this->usesTimestamps() && ! is_null($this->getUpdatedAtColumn())) {
            $this->{$this->getUpdatedAtColumn()} = $timestamp;
            $columns[$this->getUpdatedAtColumn()] = $timestamp;
        }

        $query->update($columns);

        $this->syncOriginalAttributes(array_keys($columns));

        $this->fireModelEvent('trashed', false);
    }

    public function trashed(): bool
    {
        return (int) ($this->getAttributeFromArray($this->getDeletedAtColumn()) ?? 0) > 0;
    }
}

时间戳处理机制

CatchAdmin 框架中所有数据表的 created_atupdated_at 时间字段都采用 Unix 时间戳(int 类型)进行存储。CatchModel 在初始化时会合并时间格式化配置,并保持 deleted_at 为整数:

php
protected function init(): void
{
    $this->mergeCasts(array_merge(
        $this->defaultCasts,
        $this->dateFormatCasts(),
        [$this->getDeletedAtColumn() => 'integer'],
    ));
}

时间字段行为

  • created_atupdated_at 会通过 dateFormatCasts() 序列化为配置中的日期格式
  • deleted_at 始终按整数处理,模型属性、原始值和数据库值保持同一语义
  • created_atupdated_at 是否参与自动写入取决于字段是否存在于 $fillable

软删除机制

CatchModel 采用整数软删除语义:

  • deleted_at = 0 表示正常数据
  • deleted_at > 0 表示已删除数据
  • deleted_at 存储 Unix 时间戳

TIP

CatchModel 的软删除使用方式与 Laravel 原生 SoftDelete 功能保持一致,无需额外配置。

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

    protected function addRestore(Builder $builder)
    {
        $builder->macro('restore', function (Builder $builder) {
            $builder->withTrashed();

            return $builder->update([$builder->getModel()->getDeletedAtColumn() => 0]);
        });
    }
}

当前实现还补齐了模型级软删除行为:

  • restore() 会把 deleted_at 写回 0
  • runSoftDelete() 会把数据库和当前模型实例的 deleted_at 同步写成整数时间戳
  • trashed() 通过 deleted_at > 0 判断当前模型是否处于回收站

模型属性配置

CatchModel 提供了丰富的模型属性配置选项,用于精细控制数据模型的 CRUD 操作行为、查询逻辑和数据处理特性:

数据结构相关属性

php
// 树形结构父级字段,建议使用默认值
protected string $parentIdColumn = 'parent_id';

// 排序字段配置
protected string $sortField = 'sort';
protected bool $sortDesc = true;  // 默认倒序

// 列表数据返回格式
protected bool $asTree = false;      // 是否以树形结构返回
protected bool $isPaginate = true;   // 是否启用分页

查询和表单相关属性

php
// 列表查询默认字段
protected array $fields = [];

// 表单提交字段配置
protected array $form = [];

// 关联关系处理(如用户与角色的多对多关系)
protected array $formRelations = [];

权限控制属性

php
// 数据权限控制
protected bool $dataRange = false;

// 字段权限控制
protected bool $columnAccess = false;

// 创建人自动填充
protected bool $isFillCreatorId = true;

数据处理属性

php
// 空值自动转换
protected bool $autoNull2EmptyString = true;

// 动态排序参数
protected string $dynamicQuerySortField = 'sortField';
protected string $dynamicQuerySortOrder = 'order';

模型方法详解

数据查询方法

获取列表数据

php
public function getList(): mixed

该方法是 CatchModel 的核心数据查询方法,集成了多种高级数据检索功能:

  • 字段权限过滤
  • 创建人信息关联
  • 快速搜索支持
  • 数据权限控制
  • 自定义排序规则
  • 动态排序支持
  • 分页/树形结构返回

排序规则有两层约束:

  • 默认排序字段 sortField 需要存在于 $fillable
  • 动态排序字段来自请求参数 sortField / order,字段名需要满足合法标识符格式并存在于 $fillable

列表查询自定义扩展

通过 CatchModelsetBeforeGetList 方法可以在数据查询执行前添加自定义逻辑:

php
// 添加自定义排序规则
$model->setBeforeGetList(function ($query) {
    return $query->orderByDesc('sort');
})->getList();
php
// 添加表连接
$model->setBeforeGetList(function ($query) {
    return $query->join('some_table', 'table.id', '=', 'some_table.table_id');
})->getList();
php
// 添加关联关系加载
$model->setBeforeGetList(function ($query) {
    return $query->with('someRelations');
})->getList();

数据保存方法

保存数据(单条记录)

php
public function storeBy(array $data): mixed

CatchModel 的数据保存方法,用于处理单条数据记录的数据库存储,支持 Laravel 关联关系的智能处理。操作成功返回主键 ID,失败返回 false

创建数据(批量操作)

php
public function createBy(array $data): mixed

TIP

createBy 方法适用于循环批量创建数据的业务场景,而 storeBy 更适合单条数据 CRUD 操作。它会每次创建模型实例,并且触发模型事件

示例如下,每次都是新的模型实例,每次创建都会触发模型事件

php
foreach($data as $item) {
    $model->createBy($item);
}

更新数据

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

CatchModel 的数据更新方法,根据主键 ID 更新数据记录,支持 Laravel 关联关系的同步更新。

批量更新

php
public function batchUpdate(string $field, array $condition, array $data): bool

参数说明:

参数类型说明
$fieldstring更新条件字段(如 id
$conditionarray条件值数组(如 [1, 2, 3]
$dataarray更新数据键值对

CatchModel 批量更新注意事项

  • 该方法不会触发 Laravel 模型事件
  • $field 仅允许使用 $fillable 中的字段和主键字段
  • $data 中的可更新字段仅允许使用 $fillable
  • 数据条件数量需要与每个字段的更新值数量保持一致
  • SQL 使用参数绑定,支持引号等特殊字符值

使用示例:

php
$model = new SomeModel();
$model->batchUpdate('id', [1, 2, 3], [
    'name' => ['小明', '小隋', '小书'],
    'age' => [12, 13, 14]
]);

数据查询方法

单条数据查询

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

CatchModel 的单条数据查询方法,根据指定数据库字段查询单条记录,默认使用主键 id 字段。支持数据权限和字段权限过滤。

数据删除方法

删除数据

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

CatchModel 的数据删除方法,根据主键 ID 删除数据记录,默认采用安全的软删除机制。当 $force 参数设置为 true 时进行永久物理删除。

删除软删除数据

php
public function deleteTrash($id): mixed

彻底删除已被 CatchModel 软删除标记的数据记录,执行永久性数据库删除操作。

批量删除

php
public function deletesBy(array|string $ids, bool $force = false, ?Closure $callback = null): bool

CatchModel 的批量删除方法,支持同时处理正常数据和软删除数据的批量删除操作。$ids 参数支持灵活的数据格式,可以是 PHP 数组或逗号分隔的字符串(如 "1,2,3,4,5")。

$callback 参数可用于处理删除后的回调逻辑:

php
$ids = [1, 2, 3];
$this->deletesBy($ids, false, function($ids) {
    // $ids [1, 2, 3]
    // 这里处理删除后的逻辑
});

恢复数据

php
public function restoreBy(array|string $ids): true

配合 CatchAdmin 后台管理系统的数据回收站功能,用于恢复 CatchModel 软删除的数据记录。

restoreBy() 最终会把 deleted_at 恢复为 0,与回收站查询和 trashed() 判断保持一致。

辅助功能方法

排序功能

通过设置 sortField 属性可以指定默认排序字段:

php
protected string $sortField = 'sort';

默认使用倒序排序,如需正序排序可设置:

php
protected bool $sortDesc = false;

状态切换

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

通过主键 ID 进行状态字段的切换,默认操作 status 字段。

处理树状数据的子级更新

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

递归更新树形结构中指定父级下所有子级的字段值。

字段别名处理

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

为字段添加表名前缀,避免联表查询时的字段冲突。

创建人相关方法

php
// 设置创建人 ID
public function setCreatorId()

// 获取创建人信息(Scope 查询)
public function scopeCreator()

使用创建人查询 Scope:

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'
];

CatchModel 中配置 searchable 属性后,框架会自动生成相应的数据库查询条件:

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

CatchModel 的快速搜索支持数据库别名字段,特别适用于多表 JOIN 联查询场景。例如当 A 和 B 两张表都包含 status 字段时,可以精确指定查询目标

php
// 在 CatchModel 中可以指定使用 A 表的 status 字段进行精确查询
protected array $searchable = [
    'A.status' => '=',

];

CatchModel 数据库事务处理

CatchModel 在模型类中内置集成了 Laravel 数据库事务处理方法,无需额外引入 DB Facade:

php
// 开启事务
$this->beginTransaction();

// 提交事务
$this->commit();

// 回滚事务
$this->rollback();

// 事务闭包
$this->transaction(function() {
    // 事务内的操作
});

CatchModel 事务处理便捷性

相比传统的 DB::beginTransaction() 方式,CatchModel 直接在模型中调用事务方法更加便捷,提升了 PHP 开发效率。