如何在Laravel中结合OR条件使用whereBelongsTo方法?
问题原因与解决方案
你的问题出在逻辑条件的分组优先级上,当前写法会导致归属条件脱离了原有查询的过滤规则(比如软删除deleted_at、管理员权限限制),最终导致无结果返回。
具体问题分析
你原来的代码中,当找到匹配的会员中心时,是这样拼接条件的:
$query->where(/* 搜索条件闭包 */) ->orWhere(/* 归属条件闭包 */);
结合之前已有的deleted_at和管理员权限过滤,最终生成的SQL逻辑是:
WHERE deleted_at IS NULL AND (created_by = ? OR regional_center_id = ?) AND (搜索条件) OR (归属条件)
由于SQL中AND优先级高于OR,这段逻辑等价于:(原有条件 AND 搜索条件) OR (归属条件)
这里的归属条件没有带上deleted_at和管理员权限的过滤,要么查不到符合要求的记录,要么查到的是不符合权限/已删除的记录,自然返回空。
而你单独使用whereBelongsTo时,逻辑是:原有条件 AND 归属条件
所有过滤规则都生效,所以能返回正确结果。
修复后的代码
把搜索条件和归属条件放到同一个外层闭包里,让它们共享原有条件的过滤,逻辑变成原有条件 AND (搜索条件 OR 归属条件):
if(isset($request->searchKey) && !empty($request->searchKey) && $request->searchKey !== '') { $data['searchKey'] = $request->searchKey; $searchKey = trim($data['searchKey']); $membershipCenters = MembershipCenter::where('name', 'LIKE', '%' . $searchKey . '%')->get(); // 用集合的isNotEmpty()简化判断 if($membershipCenters->isNotEmpty()) { $query->where(function ($mainOrQuery) use ($searchKey, $membershipCenters) { // 原有搜索条件 $mainOrQuery->where(function ($orQuery) use ($searchKey){ $orQuery->where('name', 'LIKE', '%' . $searchKey . '%') ->orWhere('mobile', 'LIKE', '%' . $searchKey . '%') ->orWhere('card_id', 'LIKE', '%' . $searchKey . '%') ->orWhereHas('employeeLanguage', function ($languageRelationQuery) use ($searchKey){ $languageRelationQuery->where(function($languageQueryEn) use($searchKey) { $languageQueryEn->where('name', 'LIKE', '%' . $searchKey . '%') ->where('language', 'en'); }) ->orWhere(function($olanguageQueryAr) use($searchKey) { $olanguageQueryAr->where('name', 'LIKE', '%' . $searchKey . '%') ->where('language', 'ar'); }); }); }) // 把归属条件放到同一个外层闭包的OR分支里 ->orWhere(function($belongsToQuery) use($membershipCenters) { $belongsToQuery->whereBelongsTo($membershipCenters, 'employeeMembershipCenter'); }); }); } else { // 原有搜索逻辑不变 $query->where(function ($orQuery) use ($searchKey){ $orQuery->where('name', 'LIKE', '%' . $searchKey . '%') ->orWhere('mobile', 'LIKE', '%' . $searchKey . '%') ->orWhere('card_id', 'LIKE', '%' . $searchKey . '%') ->orWhereHas('employeeLanguage', function ($languageRelationQuery) use ($searchKey){ $languageRelationQuery->where(function($languageQueryEn) use($searchKey) { $languageQueryEn->where('name', 'LIKE', '%' . $searchKey . '%') ->where('language', 'en'); }) ->orWhere(function($olanguageQueryAr) use($searchKey) { $olanguageQueryAr->where('name', 'LIKE', '%' . $searchKey . '%') ->where('language', 'ar'); }); }); }); } }
额外优化点
Laravel集合自带isNotEmpty()方法,可以替代繁琐的isset() && !empty() && count() > 0判断,代码更简洁。
内容的提问来源于stack exchange,提问作者Saswat
相关产品推荐
相关产品推荐

