Where query after whereHas not work as it should in Laravel 5.4

被刻印的时光 ゝ 提交于 2019-12-24 06:02:06

问题


In my case I have channels table that is in many to many relation with categories table.

I want to fetch the channels that their categories contain a dynamic value like doing LIKE query on title of each category. but I need to check another columns of a channel by where clause.

This is a channel structure:

[
  {
    "id": 87,
    "username": "ch1",
    "title": "ch title",
    "type": "channel",
    "members": 210424,
    "location": "tabriz",
    "created_at": "2017-05-09 01:39:44",
    "updated_at": "2017-05-16 17:19:28",
  }
]

To get what I want I run this query:

$channels = Channel::orderBy('members', 'desc')
            ->whereHas('categories', function ($query) use ($category) {
                $query->where('title', 'LIKE', '%' . $category . '%');
            })
            ->where([
                ['visible', 1],
                ['title', 'LIKE', '%' . $trend . '%'],
                ['location', 'LIKE', '%' . $location . '%'],
                ['members', '>', $members]])
            ->get();

Upper query return me all the channels like a query without whereHas clause whiles when I use 'whereHas' alone, it return channels with in category that I want!

Am I use wrong syntax? Is it true to use where and whereHas clauses side by side?

UPDATE:

I need do like query on channel's title or username, so I use orWhere but the result is as before! it returns all channels to me! like query without whereHas again. So I use this query to do it,

 $channels = Channel::orderBy('members', 'desc')
            ->whereHas('categories', function ($query) use ($category) {
                $query->where('title', 'LIKE', '%' . $category . '%');
            })
            ->where([
                ['visible', 1],
                ['title', 'LIKE', '%' . $trend . '%'],
                ['location', 'LIKE', '%' . $location . '%'],
                ['members', '>', $members]])
            ->orWhere([
                ['visible', 1],
                ['username', 'LIKE', '%' . $trend . '%'],
                ['location', 'LIKE', '%' . $location . '%'],
                ['members', '>', $members]])
            ->get();

At first I thought the problem is orderBy clause as @exprator sayed, but after adding orWhere I understood that orderBy is not my issue.


回答1:


Channel::whereHas('categories', function ($query) use ($category) {
                $query->where('title', 'LIKE', '%' . $category . '%');
            })->orderBy('members', 'desc')

use the whereHas before the order_by

->orWhere(function ($query) {
                $query->where('visible', '=', 1)
                      ->where('username', 'LIKE', '%' . $trend . '%')
                       ->where('location', 'LIKE', '%' . $location . '%')
                       ->where('members', '>', $members);
            })



回答2:


Try to just use ->whereHas() after the ->where(). You don't need to duplicate anything normally.

$channels = Channel::where([
            ['visible', 1],
            ['title', 'LIKE', '%' . $trend . '%'],
            ['location', 'LIKE', '%' . $location . '%'],
            ['members', '>', $members]])
        ->orWhere([
            ['visible', 1],
            ['username', 'LIKE', '%' . $trend . '%'],
            ['location', 'LIKE', '%' . $location . '%'],
            ['members', '>', $members]])
        ->whereHas('categories', function ($query) use ($category) {
            $query->where('title', 'LIKE', '%' . $category . '%');
        })
        ->orderBy('members', 'desc')
        ->get();



回答3:


whereHas() is wrongly used with where() and orWhere(). after whereHas the second and third conditions have to be combined in a sub-routine. Currently your query will look like this:

SELECT * FROM foo WHERE something_where_has 1 AND WHERE something 2 OR WHERE something 3 ..

but I think what you wanted is your condition to look like this:

SELECT * FROM foo WHERE something_where_has 1 AND (WHERE something 2 OR WHERE something 3) ..

So this may serve you:

->whereHas('categories', function ($query) use ($category) {
                $query->where('title', 'LIKE', '%' . $category . '%');
            })
->where(function($q) {
             $q->where([
                ['visible', 1],
                ['title', 'LIKE', '%' . $trend . '%'],
                ['location', 'LIKE', '%' . $location . '%'],
                ['members', '>', $members]])
             ->orWhere([
                ['visible', 1],
                ['username', 'LIKE', '%' . $trend . '%'],
                ['location', 'LIKE', '%' . $location . '%'],
                ['members', '>', $members]]);
                })  



回答4:


I solved this issue by duplicating whereHas clause after orWhere. So to fetch the channels that are in categories that I want, I used this query:

$channels = Channel::orderBy('members', 'desc')
            ->whereHas('categories', function ($query) use ($category) {
                $query->where('title', 'LIKE', '%' . $category . '%');
            })
            ->where([
                ['visible', 1],
                ['title', 'LIKE', '%' . $trend . '%'],
                ['location', 'LIKE', '%' . $location . '%'],
                ['members', '>', $members]])
            ->orWhere([
                ['visible', 1],
                ['username', 'LIKE', '%' . $trend . '%'],
                ['location', 'LIKE', '%' . $location . '%'],
                ['members', '>', $members]])
            ->whereHas('categories', function ($query) use ($category) {
                $query->where('title', 'LIKE', '%' . $category . '%');
            })
            ->get();

Maybe it's strange but worked nice!



来源:https://stackoverflow.com/questions/44582775/where-query-after-wherehas-not-work-as-it-should-in-laravel-5-4

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!