外观
模型、查询与服务层
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')。- 混入
HasCache、HasEvents、HasMetadata和HasQueryable。
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('id | name')` |
Pin\Validation\Q 是 Pin\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 对象
创建、更新和删除分别返回:
CreateResultUpdateResultDeleteResult
这些对象实现 Arrayable 和 JsonSerializable,并提供 message()。ApiResponse 在没有显式 message 时会优先使用 Result 的 message。