模型
多对多
class User extends Model
{
public function roles()
{
// Role::class 实际关联表
// user_role 中间表
// user_rid 中间表中主表的字段(主表还是关联表是相对而言的,在Role.php中,role表就是主表)
// role_rid 中间表中被关联表的字段
// rid 主表字段(如果和中间表中主表的字段名称不一样需要设置)
// rid 实际关联表字段(如果和中间表中被关联表的字段名称不一样需要设置)
return $this->belongsToMany(Role::class, "user_role", "user_rid", "role_rid", 'rid', 'rid')->wherePivot("status", 1)->wherePivotIn("role_rid", [1, 2, 3]);
}
}
预加载
// 嵌套预加载 with xxx.xxx
Order::withOrderProductQuery()->with(["metas","stats","products.metas"])->limit(10)->get();
// 嵌套预加载,方式2
$qb->with(["detail" => function ($qb) {
// 在内部,进行 .xxx 的嵌套预加载
$qb->with(["xxx" => function ($subQb) {
$subQb->select(["id", "code", "name"]);
}])->select(["id", "code", "name"]);
}]);
// 大小写,方法和with都使用小驼峰,其他地方直接使用下划线,比如:sup_supplier
Order::withOrderProductQuery()->with(["supSupplier"])->limit(10)->get();
// 预加载过滤(不影响主表)
Order::withOrderProductQuery()->with(["metas" => function($query) {
$query->where('xxx', "xxx");
$query->orderBy('xxx.xxx', 'DESC');
}])->limit(10)->get();
// 关联过滤exists,a表数据量 < b表数据量时使用,SELECT * FROM a WHERE EXISTS(SELECT * FROM b WHERE a.xx = b.xx )
$qb->whereHas('metas', function ($qb) use ($params) {
$qb->where("xxx", $params['xxx']);
});
// 关联过滤in,a表数据量 > b表数据量时使用,SELECT * FROM a WHERE id IN (SELECT id FROM b )
$qb->whereIn("id", function($qb) use ($params) {
$qb->select("id")->where("xxx", $params["xxx"])->FROM("b");
});
// 预加载统计
$users = User::withCount([
'posts',
'comments',
'comments as approved_comments_count' => function ($query) {
$query->where('approved', 1);
}])
->get();
// 上面两种方式不能命中索引,可以在父类封装一个给whereIn用的数组,比如:
public static function getRelationWhereInData($params, $key)
{
return static::queryWithParams($params)->select($key)->pluck($key)->unique()->toArray();
}
多态关联
需要根据不同关联类型关联不同表的场景(如:relation_type
、relation_id
),可以考虑使用多态关联
生成模型
如果模型太多,可能会内存溢出,增加 memory_limit
php -d memory_limit=-1 bin/hyperf.php gen:model