模型
多对多
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();
// 预加载过滤(不影响主表)
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
),可以考虑使用多态关联