Skip to content

模型、查询与服务层

Pin 的模型层提供 Pin\Models\Model、查询 DSL、排序分页宏、缓存能力和通用 ModelService

基础模型

php
namespace App\Models;

use Pin\Models\Model;

class User extends Model
{
    protected $table = 'users';
}

Pin\Models\Model 默认:

  • $guarded = [],允许批量赋值。
  • 日期序列化为 Y-m-d H:i:s
  • JSON 字段通过 Pin\Support\Json::encode() 编码。
  • getTable() 使用 Memoize 缓存。
  • getPerPage() 默认读取 config('pagination.default_page_size')
  • 混入 HasCacheHasEventsHasMetadataHasQueryable

Queryable

Queryable 把请求参数和查询规则绑定起来,再由 Builder 宏 q() 应用到 Eloquent。

php
use Pin\Models\Queryable\Queryable;
use Pin\Validation\Q;

$queryable = Queryable::fromRules([
    'keyword' => Q::ns('id|username'),
    'status' => Q::inN(),
    'created_at' => Q::range(),
]);

$users = User::query()
    ->q($queryable)
    ->pagination();

常用规则:

规则查询语义
QueryableRule::eq() / eqN()字符串或数值等于
QueryableRule::like()%value% 模糊匹配
startsWith() / endsWith()前缀或后缀匹配
gt() / gte() / lt() / lte()字符串比较
gtN() / gteN() / ltN() / lteN()数值比较
in() / inN()whereIn
range() / rangeN()区间查询
`ns('idname')`

Pin\Validation\QPin\Validation\QueryRules 的别名,适合直接写进 Laravel validation rules。

自定义字段搜索

模型可以定义 search{Field} 方法接管某个字段的查询。

php
use Illuminate\Database\Eloquent\Builder;

class User extends Model
{
    public function searchKeyword(Builder $builder, string $value, array $reqs): void
    {
        $builder->where(function (Builder $query) use ($value) {
            $query
                ->where('username', 'like', "%{$value}%")
                ->orWhere('email', 'like', "%{$value}%");
        });
    }
}

默认字段名会通过 transformQueryableColumn() 转为 snake case,可在模型中覆盖。

排序与分页

排序使用 sort($value, $allows),降序字段加 -

php
User::query()
    ->sort('-created_at,name', ['created_at', 'name'])
    ->pagination();

分页返回 Pin\Pagination\Pagination 包装对象,页码和每页数量参数名来自 config/pagination.php

ModelService

Pin\Services\ModelService 封装标准增删改查流程。

php
namespace App\Services;

use App\Models\User;
use Pin\Services\ModelService;

/**
 * @extends ModelService<User>
 */
class UserService extends ModelService
{
    protected function creating(array &$data): void
    {
        $data['username'] = strtolower($data['username']);
    }
}

ModelService 会根据服务类名通过 ModuleInspector 推导模型。需要显式绑定时可以使用:

php
$service = app(UserService::class)->withModel(User::class);

常用方法:

php
$result = app(UserService::class)->create($payload);
$result = app(UserService::class)->update($userId, $payload);
$result = app(UserService::class)->delete($userId);
$page = app(UserService::class)->paginate($queryable);

生命周期钩子:

钩子触发时机
saving($model, &$data)创建或更新前
creating(&$data)创建前
created($model, $data)创建后
updating($model, &$data)更新前
updated($model, $data)更新后
saved($model, $data)创建或更新成功后
deleting($model)删除前
deleted($model)删除后

如果更新数据包含 v 字段,HandlesUpdate 会做数据版本校验,并在成功后自增版本号。

Result 对象

创建、更新和删除分别返回:

  • CreateResult
  • UpdateResult
  • DeleteResult

这些对象实现 ArrayableJsonSerializable,并提供 message()ApiResponse 在没有显式 message 时会优先使用 Result 的 message。