Laravel красноречиво вложен, где возвращает все

#php #mysql #laravel #eloquent

Вопрос:

у меня есть эти таблицы с отношениями:

 -categories (has many products)
-products (has many features)
-features
 

я пытаюсь получить специальную категорию, используя ее слиток, и получить продукты в категории, а также я хочу отфильтровать продукты по некоторым функциям, используя (id)

мой код:

 $category = Category::whereHas('products', function ($query) {
    $query->whereHas('features', function ($query2) {
        $query2->where('id', 21); // Example id (products where has features with '21' id)
    });
})->where('slug', 'category-slug')
  ->with('products:id,title', 'products.features')->get();
 

но код возвращает эту категорию со всеми продуктами (с функциями или без них с идентификатором 21).

каково же решение?

Комментарии:

1. Является ли код не выполняемым $query2 условием только тогда, когда вы используете переменную, или он также не выполняется, когда вы его жестко закодировали?

2. @МухамадРафиПамунгкас да. в каждом режиме он не работает, и он вернет все товары в категории

Ответ №1:

Возможно, вы захотите попробовать точечную нотацию:

 $category = Category::whereHas('products.features', function ($query) {
        $query->whereKey(21);
    })
    ->where('slug', 'category-slug')
    ->with('products:id,title', 'products.features')->get();
 

Комментарии:

1. к сожалению, он по-прежнему возвращает все продукты со всеми функциями (с 21 идентификатором или без него).

2. @K1-Точечная нотация Aria должна работать так, как указано в документации , она должна работать. Сделайте это, вместо того, чтобы запускать ->get() , замените его на ->toSql() и поделитесь результатами с нами здесь, пожалуйста.

Ответ №2:

Я думаю, что лучше использовать сводную таблицу, в которой хранятся характеристики продукта.

  ------------------ 
| categories       |
| features         |
| feature_product  |
| products         |
 ------------------ 
 

Обратите внимание, что имя сводной таблицы должно располагаться в алфавитном порядке до соглашения Laravel.

Столбцы feature_product:

  ------------ --------- ------ ----- --------- ---------------- 
| Field      | Type    | Null | Key | Default | Extra          |
 ------------ --------- ------ ----- --------- ---------------- 
| id         | int(11) | NO   | PRI | NULL    | auto_increment |
| product_id | int(11) | YES  |     | NULL    |                |
| feature_id | int(11) | YES  |     | NULL    |                |
 ------------ --------- ------ ----- --------- ---------------- 
 

Теперь добавьте отношение к вашей модели продукта:

 public function features() {
    return $this->belongsToMany(Feature::class);
}
 

Запрос:

 $products = Product::select()
        ->join('feature_product', function ($join) {
            $join->on('feature_product.product_id', 'products.id')
                ->where('feature_id', 21);
        })
        ->join('categories', function ($join) {
            $join->on('products.category_id', 'categories.id')
                ->where('slug', 'slug-name');
        }) 
        ->get();
 

Теперь получите функции для каждого продукта:

 foreach ($products as $product) {
         $product->features;
}