Laravel中不使用join实现多表关联的替代方案咨询
不使用JOIN的Eloquent多表关联实现方案
第一步:定义模型间的关联关系
首先要在Eloquent模型中明确表之间的关联,这是替代JOIN的核心:
User 模型(app/Models/User.php)
// 一个用户对应一条理发师记录 public function barber() { return $this->hasOne(Barber::class, 'id_user'); }
Barber 模型(app/Models/Barber.php)
// 理发师归属一个用户 public function user() { return $this->belongsTo(User::class, 'id_user'); } // 一个理发师对应多条评价 public function avis() { return $this->hasMany(Avis::class, 'id_barber'); } // 一个理发师对应多条订单(对应原查询中的commandes) public function commandes() { return $this->hasMany(Commande::class, 'id_barber'); }
第二步:重写查询逻辑(无JOIN版)
利用Eloquent的with(预加载关联数据)、whereHas(筛选关联满足条件的主模型)方法替代JOIN,实现相同业务逻辑:
$barbers = Barber::with('user') // 关联用户必须为已验证状态 ->whereHas('user', function($query) { $query->where('isValidate', true); }) // 筛选理发师状态为1或4 ->whereIn('id_state', [1, 4]) // 筛选订单数量达标理发师 ->whereHas('commandes', function($query) use ($searchTermes1) { $query->groupBy('id_barber') ->havingRaw('count(*) >= ?', [(int)$searchTermes1]); }) // 确保理发师存在对应评价记录(对应原查询的JOIN avis) ->whereHas('avis') // 搜索匹配逻辑:理发师名称 或 用户姓名组合 ->where(function($query) use ($searchTerm) { $query->where('name_barber', 'like', "%{$searchTerm}%") ->orWhereHas('user', function($userQuery) use ($searchTerm) { $userQuery->whereRaw("concat(first_name, ' ', last_name) like ?", ["%{$searchTerm}%"]) ->orWhereRaw("concat(last_name, ' ', first_name) like ?", ["%{$searchTerm}%"]); }); }) // 按理发师创建时间倒序排序 ->orderBy('created_at', 'desc') // 分页返回结果 ->paginate(10);
逻辑说明
with('user'):预加载关联用户数据,避免N+1查询问题,替代原查询中SELECT users.*的需求whereHas:用于筛选主模型(Barber)存在满足条件的关联模型(User、commandes、avis),替代JOIN后的条件筛选- 所有条件通过关联关系传递,完全避免手动编写JOIN语句,符合Eloquent的ORM设计思想
内容的提问来源于stack exchange,提问作者Roronoa Zoro
相关产品推荐
相关产品推荐

