如何通过关联函数及关联字段过滤AuthorProfiles查询结果?
Laravel 关联模型过滤实现方案
一、匹配 User 的 first_name 或 surname 字段
假设你的 AuthorProfile 模型已定义与 User 的关联方法(比如 user(),返回 belongsTo(User::class)),可以通过 whereHas 实现关联表字段的过滤:
if($this->search != "") { $searchTerm = '%' . $this->search . '%'; $authors = $authors->where('author_profile', 'like', $searchTerm) ->orWhere('author_slug', 'like', $searchTerm) // 过滤关联 User 的 first_name 或 surname ->orWhereHas('user', function($query) use ($searchTerm) { $query->where('first_name', 'like', $searchTerm) ->orWhere('surname', 'like', $searchTerm); }); }
二、匹配 User::getName() 的拼接值
getName() 是模型方法,返回 first_name 和 surname 的拼接结果,直接在数据库层面用 DB::raw 模拟该拼接逻辑即可实现匹配:
use Illuminate\Support\Facades\DB; if($this->search != "") { $searchTerm = '%' . $this->search . '%'; $authors = $authors->where('author_profile', 'like', $searchTerm) ->orWhere('author_slug', 'like', $searchTerm) ->orWhereHas('user', function($query) use ($searchTerm) { $query->where('first_name', 'like', $searchTerm) ->orWhere('surname', 'like', $searchTerm) // 模拟 getName() 的拼接逻辑,注意分隔符与方法内一致 ->orWhere(DB::raw('CONCAT(first_name, " ", surname)'), 'like', $searchTerm); }); }
注意:如果
getName()中使用的分隔符不是空格(比如逗号),请修改CONCAT内的分隔符与之匹配。
三、关联模型过滤通用方法
1. 关联字段直接过滤
使用 whereHas 方法,传入关联方法名(如上述的 user),在闭包内对关联表的字段添加查询条件。这种方式基于数据库关联查询,效率较高,适合直接查询关联表的存储字段。
2. 关联模型方法返回值过滤
- 如果方法逻辑仅基于数据库字段的拼接/计算:用
DB::raw模拟方法逻辑,将计算放到数据库层面完成(如上述拼接姓名的例子)。 - 如果方法涉及复杂逻辑(如调用外部服务、处理非数据库字段):需先获取所有关联数据后在内存中过滤,但这种方式效率较低,数据量大时不建议使用。
3. 注意事项
- 确保模型中已正确定义关联关系(
belongsTo/hasMany等)。 - 闭包中需通过
use ($变量)传递外部查询参数。 - 模糊查询提前拼接
%$searchTerm%,减少重复代码。 - 大小写敏感设置:MySQL 的
like默认不区分大小写,PostgreSQL 可改用ILIKE。
内容的提问来源于stack exchange,提问作者Giles Bennett
相关产品推荐
相关产品推荐

