【问题标题】:Filter model with HasMany relationship具有 HasMany 关系的过滤器模型
【发布时间】:2018-06-16 03:01:34
【问题描述】:

假设我有两个模型:ParkItems。每个Park 可以有多个Items,通过HasMany 关系。

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;

【问题讨论】:

  • 几个问题:1) 你使用的是什么版本的 Laravel? 2) dd( json_decode($request->type_list)); 的输出是什么? 3) 请您解释一下它是如何工作不正常的
  • 您好罗斯,抱歉信息不足。 1)5.4 2)[“ag”,“zd”](这工作正常) 3)我没有得到一个包含所有项目类型的公园列表,而是一个包含一些项目类型的公园列表。我需要满足所有条件的公园集合。

标签: laravel eloquent has-many


【解决方案1】:

您可以在 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();

【讨论】:

  • 嗨拉尔特。感谢您的回答,但我得到了相同的结果。我获得了包含一些物品的公园集合,但我需要包含所有物品的公园。我想我缺少某种“加入”语句,但我不知道如何实现它。
  • 好的,现在我明白你需要什么了。我会编辑答案。
  • 请检查编辑后的答案是否解决了问题。
  • 嗯,我想我们在同一点上。首先,'andWhere' 语句出现错误,因为它不存在,如果我用 'where' 或 'orWhere' 替换它,我会得到类似的结果。我正在尝试一种不同的方法,为每种项目类型获取不同的集合,然后将它们相交。
  • 我从orWhere 的代码中复制了这段代码,对不起。但是,这应该可以工作,因为它在 where 子句中创建了几个 AND 语句。
【解决方案2】:

我认为使用 where 子句匹配同一行的所有项目的类型不会产生任何结果,这就像做 where id = 1 and id = 2 一样,这是不可能的,因为 id 只能取一个值,你应该做的是使用 whereIn 来获取与至少一种类型匹配的所有项目,然后使用groupBy 将结果按park_id 分组,然后在have 子句中检查组计数是否等于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();

【讨论】:

  • 您好 YouneL,我明白了,您是对的,但我收到此错误:SQLSTATE[42000]:语法错误或访问冲突:1055 SELECT 列表的表达式 #1 不在 GROUP BY 中子句并包含非聚合列“****.items.type”,它在功能上不依赖于 GROUP BY 子句中的列;这与 sql_mode=only_full_group_by 不兼容(SQL:select * from parks where exists (select type, COUNT(park_id) from items where parks.id = items.park_id 和 @ 987654334@ in (ai) group by park_id 有 COUNT(park_id) = 1))
  • 对不起,选择方法应该是$q->select('park_id', DB::raw('COUNT(park_id)')),我更新了答案
【解决方案3】:

您可以在一个查询中添加多个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();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-19
    • 1970-01-01
    • 2023-04-09
    • 2015-10-21
    相关资源
    最近更新 更多