Laravel whereNotIn не работает как подзапрос

Здравствуйте замечательные люди ТАК!

У меня есть проблема, которую я не могу решить самостоятельно даже после поиска, поиска в Google и прочтения стольких статей.

У меня 3 модели:

  1. User

  2. Food

  3. Ingredient

    User.php
    
    public function favourites()
    {    
           return $this->belongsToMany(Food::class, 'food_user', 'user_id', 'food_id', 'id', 'id');
    }`
    
    // Some people dislike some ingredient(s) or alergic to it
    public function dislikes()
    {
           return $this->belongsToMany(Ingredient::class, 'ingredient_user', 'user_id', 'ingredient_id', 'id', 'id');
    }
    
    Food.php
    
    public function likes()
    {
           return $this->belongsToMany(User::class, 'food_user', 'food_id', 'user_id', 'id', 'id');
    }
    
    public function ingredients()
    {
           return $this->belongsToMany(Ingredient::class, 'food_ingredient', 'food_id', 'ingredient_id', 'id', 'id');
    }
    
    Ingredient.php
    
    public function foods()
    {
           return $this->belongsToMany(Food::class, 'food_ingredient', 'ingredient_id', 'food_id', 'id', 'id');
    }
    
    public function disliked()
    {
           return $this->belongsToMany(User::class, 'ingredient_user', 'ingredient_id', 'user_id', 'id', 'id');
    

}

Итак, после установки этих отношений, теперь я хочу реализовать поисковую систему

SearchController.php

use ...
use ...

public function foods(Request $request)
{
    $user = User::with(['dislikes'])->find(x);

    $dislikes = $user->dislikes->pluck('pivot')->pluck('ingredient_id')->toArray();

    $query = $request->query('keyword');

    $builder = Food::query()->with(['ingredients']);

    $builder->where('name', 'LIKE', "%$query%");

    $builder->orWhereHas('ingredients', function ($query) use ($dislikes) {
        // This is not working, it STILL fetch all food with ingredients the current user dislikes
        $query->whereNotIn('ingredient_id', $dislikes);
    });

    $foods = $builder->get();

    return ...
}

Любая идея, почемуwhereNotIn() не работает внутриorWhereHas() пункт?

заранее спасибо

# database
Источник
  • 0
    dd ($ dislikes) что вы получаете
  • 0
    Идентификаторы нежелательных ингредиентов: [3, 7, 10]
  • 0
    хорошо. позвольте мне еще раз проанализировать ваш запрос, так как он хорошо выглядит
  • 0
    попробуйте или где есть где есть
  • 0
    orWhereHas станет необязательным, поэтому выбираются все
  • 0
    Если я правильно понимаю, orWhereHas все соответствующие записи с / без него (CMIW), а другая сторона whereHas все соответствующие записи, которые имеют отношение к нему
  • 0
    так как у вас есть -> с (['ингредиенты']), он вернет все
  • 0
    Хорошо, позволь мне проверить это
  • 0
    $ builder = Food :: query () -> with (['components' => function ($ query) use ($ dislikes) {$ query-> whereNotIn ('ингридиент_id', $ не нравится);}]); $ builder-> where ('имя', 'НРАВИТСЯ', "% $ query%"); $ food = $ builder-> получить ();
  • 0
    если он все еще не работает, вы можете попробовать $ builder = Food :: query () -> when (count ($ dislikes), function ($ q) use ($ dislikes) {$ q-> whereHas ('components', function ( $ query) use ($ dislikes) {$ query-> whereNotIn ('ингридиент_id', $ dislikes);});}); $ builder-> where ('имя', 'НРАВИТСЯ', "% $ query%"); $ food = $ builder-> получить ();
  • 0
    он работает и дает ожидаемый результат. Какие правила / положения я должен соблюдать? Я никогда не изучаю SQL , так как я из front-end
  • 1
    просто напечатайте qurey, если он не работает, тогда вы поймете, в каком случае не работает
Codelisting
за 1 против
Лучший ответ

Вы должны изменить свой запрос, так как with вернет все результаты, независимо от условий в вашем случае.

$builder = Food::query()->with(['ingredients'=>function ($query) use ($dislikes) {
     $query->whereNotIn('ingredient_id', $dislikes);
     }]); 
    $builder->where('name', 'LIKE', "%$query%"); 
    $foods = $builder->get(); 

вы можете использовать обратный вызов внутри с отношением или вы можете использовать обратный вызов, как показано ниже

$builder = Food::query()->when(count($dislikes),function ($q) use ($dislikes){
 $q->whereHas('ingredients',function ($query) use ($dislikes) {
 $query->whereNotIn('ingredient_id', $dislikes);
 }); 
}); 
$builder->where('name', 'LIKE', "%$query%"); 
$foods = $builder->get(); 
  • 0
    @ ChristianDelvianto.нет проблем. Рад, что вы решили свою проблему
за 1 против

Замените orWHereHas на WhereHas, так как вы используете whereNotIn

  • 0
    Привет спасибо за ответ но боюсь вы опоздали, извини
Codelisting
Популярные категории
На заметку программисту