为了账号安全,请及时绑定邮箱和手机立即绑定

Laravel 雄辩:如何用 where() 和 whereHas() 过滤

Laravel 雄辩:如何用 where() 和 whereHas() 过滤

PHP
一只甜甜圈 2021-11-26 15:43:12
我正在尝试根据他们发布内容的类别以及用户直接通过搜索字符串过滤我的用户:$users = User::when($search, function ($query) use ($request) {    $query->where('name', 'like', '%' . $request['search'] . '%')          ->orWhere('email', 'like', '%' . $request['search'] . '%');    return $query;})->when($categories, function ($query) use ($request) {    return $query->whereHas('posts.category', function ($query) use ($request) {        $query->whereIn('name', $request['categories']);    });})->select('id', 'name', 'email')->paginate(10);当我只过滤类别(没有$search)时,它按预期工作,但只要我输入搜索字符串,结果就会被搜索字符串过滤,$request['search']但完全忽略类别过滤。例如:名为“Jon”的用户在“生活方式”类别中有一个帖子。另一个名为“Jonn”的用户在“体育”类别中有一个帖子。现在,如果我只过滤“体育”类别,我会得到正确的结果 ->“乔恩”。但是,如果我使用搜索字符串“Jon”进行额外过滤,结果是 ->“Jon”和“Jonn”,这不是预期的结果,因为它应该过滤“Sports”并命名“%Jon%”,因此结果应该再次只是“乔恩”。我不知道我怎么能实现该过滤器组合where()和whereHas()。
查看完整描述

2 回答

?
慕婉清6462132

TA贡献1804条经验 获得超2个赞

你可以这样试试:


$users = User::where(function ($query) {

    $query->when($search, function ($query) use ($request) {

        $query->where('name', 'like', '%' . $request['search'] . '%')

          ->orWhere('address', 'like', '%' . $request['search'] . '%')

          ->orWhere('email', 'like', '%' . $request['search'] . '%');

        })

    $query->when($categories, function ($query) use ($request) {

           $query->whereHas('posts.category', function ($query) use ($request) {

           $query->whereIn('name', $request['categories']);

        });

    })

})

->select('id', 'name', 'email')

->paginate(10);

我认为你不需要你的回报。但是,如果您将when语句放在这样的一个where函数中,您就可以实现您想要的。


我没有测试这个解决方案,所以如果你有错误,请在评论中提供它。


查看完整回答
反对 回复 2021-11-26
?
慕雪6442864

TA贡献1812条经验 获得超5个赞

您的问题是约束的嵌套。转换为 SQL,您的查询如下所示:


SELECT id, name, email

FROM users

WHERE name like '%foo%'

   OR address like '%foo%'

   OR email like '%foo%'

  AND EXISTS (

    SELECT *

    FROM categories c

      INNER JOIN posts p ON p.category_id = c.id

    WHERE c.name IN ('bar', 'baz')

  )

注意:分页省略


如您所见,目前还不清楚这些WHERE语句应该做什么。但这可以通过将所有搜索约束包装在一个额外的内容中来轻松解决where():


$users = User::when($search, function ($query) use ($request) {

    $query->where(function $query) use ($request) {

        $query->where('name', 'like', '%' . $request['search'] . '%')

            ->orWhere('address', 'like', '%' . $request['search'] . '%')

            ->orWhere('email', 'like', '%' . $request['search'] . '%');

    });

})

->when($categories, function ($query) use ($request) {

    $query->whereHas('posts.category', function ($query) use ($request) {

        $query->whereIn('name', $request['categories']);

    });

})

->select('id', 'name', 'email')

->paginate(10);

这样您的查询将如下所示:


SELECT id, name, email

FROM users

WHERE

  (

     name like '%foo%'

     OR address like '%foo%'

     OR email like '%foo%'

  )

  AND EXISTS (

    SELECT *

    FROM categories c

      INNER JOIN posts p ON p.category_id = c.id

    WHERE c.name IN ('bar', 'baz')

  )

旁边的一个小说明:您不必$query从回调中返回。


查看完整回答
反对 回复 2021-11-26
  • 2 回答
  • 0 关注
  • 319 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信