【问题标题】:Laravel - conditional filtering with relation tableLaravel - 使用关系表进行条件过滤
【发布时间】:2020-07-02 12:32:46
【问题描述】:

我必须根据$search 是否存在,有条件地过滤以下查询中的结果。 以下是我的查询,

    Sellers::with(
        'shop:id,width,height,business_id'
    )->with(
        'unit.location:id,name as l_name'
    )->select(
        'sellers.id', 'sellers.name' , 'address'
    )->when($search, function ($query, $search) {
         $query->where('l_name', 'like', '%' . $search . '%');
    })
    ->findOrFail($request->seller_id);

关系是,

卖家有很多单位。 单位有一个位置。

我需要根据搜索参数的可用性过滤上述位置名称的结果。 我尝试添加别名,但它们会抛出错误。

如何做到这一点?

【问题讨论】:

  • 你可以查看whereHas - 查询关系存在
  • 试过了。它似乎不适用于 unit.location 之类的关系。
  • 它适用于嵌套关系
  • 它抛出什么错误?也试试这个代码function ($query) use ($search) 而不是function ($query, $search)
  • @lagbox 这就是我尝试过的。卖家::with('widget:id,width,height,business_id')->whereHas('unit.location', function($q) use($search) { $q->where('locations.name', $search); }) ->select( '*' ) ->findOrFail($request->seller_id);位置数组在所有情况下都是空的。我在这里做错了什么?

标签: laravel laravel-5 eloquent laravel-7


【解决方案1】:

查询构建器中的with 表达式使用第二个查询加载关系,例如:

select * from posts; // returns posts with ids 1, 2, 3
select * from comments where posts_id in (1,2,3);

所以对于您的查询: $query->where('l_name', 'like', '%' . $search . '%'); 导致 SQL 错误,因为未连接位置表。

您有两种查询方式:

使用连接:

将您的位置表的连接添加到您的查询中

   ->join('units', ...)
   ->join('locations', ...)

通过查询关系:

将示例中的 when 表达式替换为:

    ->when($search, function ($query, $search) {
         $query->whereHas('unit.location', function () {
            $query->where('l_name', 'like', '%' . $search . '%');
         });
    })

这将在限制搜索结果的位置表上添加一个where exists 表达式。例如: (`select * from posts where exists (select 1 from comments where approved = true and comments.post_id = posts.id ))

【讨论】:

  • 我试过了,Sellers::with( 'widget:id,width,height,business_id') ->with( 'unit.location' ) ->when($search, function ($query ) 使用 ($search) { $query->whereHas('unit.location', 函数 ($query) 使用 ($search) { $query->where('id', 2); }); }) -> findOrFail($request->seller_id); whereHas 中的过滤器仍然无法正常工作。它总是列出所有结果。
  • 您能否使用toSql() 调试SQL> 另外,由于列名冲突,最好在Where Exists 中使用表的全名编写查询。 (例如$query->where('locations.id', 2);
  • 也像你提到的,位置表已加入,unit.location 语法将自动加入它。显示所有位置,问题是何时将过滤器应用于位置名称或 ID。
  • 不,unit.location 不使用连接,这就是导致错误的原因。 Laravel 将进行多个查询以加载关系(每个表每个)。请重新检查答案第一部分中的示例。
猜你喜欢
  • 2020-12-17
  • 2018-02-21
  • 1970-01-01
  • 1970-01-01
  • 2018-08-22
  • 1970-01-01
  • 2016-07-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多