猿问

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

我正在尝试根据他们发布内容的类别以及用户直接通过搜索字符串过滤我的用户:


$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()。


一只甜甜圈
浏览 320回答 2
2回答

慕婉清6462132

你可以这样试试:$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函数中,您就可以实现您想要的。我没有测试这个解决方案,所以如果你有错误,请在评论中提供它。

慕雪6442864

您的问题是约束的嵌套。转换为 SQL,您的查询如下所示:SELECT id, name, emailFROM usersWHERE 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, emailFROM usersWHERE  (     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从回调中返回。
随时随地看视频慕课网APP
我要回答