Laravel 5.6:如何按子模型筛选父模型并保留全部关联子数据?
解决方案:用
whereHas筛选父模型 + 无限制预加载全部属性 你遇到的问题很典型——with()方法里的闭包只会过滤预加载的关联数据,而不会筛选父模型(Product)本身。所以你会得到所有Product,只是它们的properties被过滤成仅匹配的条目,甚至空数组。
要实现「仅返回拥有指定属性的Product,同时保留该Product的所有属性」,需要把筛选父模型和预加载全部关联分开处理:
正确的代码实现
$products = Product::whereHas('properties', function($query){ $query->where('name', 'testproperty'); })->with('properties')->get();
代码解释
whereHas('properties', ...):这个方法会检查每个Product是否存在满足条件的properties关联记录,只返回那些有匹配属性的Product,直接排除了没有符合条件属性的Product(比如你例子里的id=2的test2)。with('properties'):这个方法负责预加载选中Product的全部属性,不会做任何过滤,所以你能拿到该Product所有的properties数据。
输出结果验证
运行这段代码后,你会得到期望的结果:
{ "id": 1, "name": "test", "properties": [ { "id": 1, "name": "testproperty", "value": "testvalue" }, { "id": 2, "name": "testproperty2", "value": "testvalue2" } ] }
额外说明
如果需要更复杂的筛选(比如多个属性条件),可以叠加whereHas来实现,比如:
// 筛选同时拥有testproperty和testproperty2的Product $products = Product::whereHas('properties', function($query){ $query->where('name', 'testproperty'); })->whereHas('properties', function($query){ $query->where('name', 'testproperty2'); })->with('properties')->get();
内容的提问来源于stack exchange,提问作者Stefan
相关产品推荐
相关产品推荐

