假设我有两个模型:Park
和Items
。每个Park
都可以通过HasMany
关系Items
。
Items
桌子上有一个park_id
场和一个type
旗:Item
可以是喷泉,篮球场或其他任何东西。
我需要做的是过滤公园,以仅获取那些在数组中传递了所有项目类型的公园。这是我所拥有的:
$parks = Park::whereHas('items', function($q) use ($request) {
$q->where('type', json_decode($request->type_list));
})->get();
但它无法正常工作。有什么想法吗?
非常感谢,祝大家新年快乐!
编辑:我找到了一个可行的解决方案,尽管非常丑陋:
$types_array = json_decode($request->type_list, true);
$results = [];
// A collection of parks for each item type
foreach($types_array as $type) {
$results[] = Park::whereHas('items', function($q) use ($type) {
$q->where('type', $type);
})->get();
}
// Intersect all collections
$parks = $results[0];
array_shift($results);
foreach ($results as $collection) {
$parks = $collection->intersect($parks);
}
return $parks;
您可以在wherehas方法中使用foreach。它应该是这样的:
$array = json_decode($request->type_list, true)
$parks = Park::whereHas('items', function($q) use ($array) {
foreach ($array as $key => $type) {
$q->where('type', $type);
}
})->get();
where 子句匹配同一行的所有项目类型不会产生任何结果,这就像做where id = 1 and id = 2
这是不可能的,因为 id 只能取一个值,你应该做的是使用 whereIn
获取至少匹配一种类型的所有项目,然后使用 groupBy
按park_id
对结果进行分组, 然后在 HAVING 子句中,您可以检查组计数是否等于type_list
计数:
$types = json_decode($request->type_list, true);
$parks = Park::whereHas('items', function($q) use ($types) {
$q->select('park_id', DB::raw('COUNT(park_id)'))
->whereIn('type', $types)
->groupBy('park_id')
->havingRaw('COUNT(park_id) = ?', [ count($types) ]);
})->get();
您可以向一个查询添加多个whereHas()
约束:
$types_array = json_decode($request->type_list, true);
$query = Park::query();
foreach($types_array as $type) {
$query->whereHas('items', function($q) use($type) {
$q->where('type', $type);
});
}
$parks = $query->get();