Как получить категории и товары через бренд?

Всем привет. Пишу сайт на laravel, но столкнулся с проблемой:

### У меня есть:

1. Запчасти
2. Бренды
3. Категории

# Запчасти имеют связи:
1. belongsTo (Бренды)
2. belongsToMany(PartCategory::class, 'pivot_part_categories', 'part_id', 'category_id' );

# Бренды имеют связь:
1. hasMany(Part::class)

# Категории имеют связь:
1. belongsToMany(Part::class, 'pivot_part_categories', 'category_id', 'part_id');

Классический вывод каталога построил, показать все запчасти, где бренд такой-то сделал.

# Не пойму, как сделать такой каталог:

Нажимаем на какой-то бренд, затем показываем все категории товаров, которые принадлежат запчастям, у которых бренд == выбранному(по которому нажали)

# Примеры того, что мне нужно:
5e3ecf43bf80c875219691.png
5e3ecf4d2ce23454914753.png

# Что я уже сделал и как пытался решить вопрос:
---------------------------------------------------------------
Мои routes имеют вид:
Route::get('/part/{slug}', 'Parts\PartController@show')->name('part.show');
Route::get('/category/{slug}', 'Parts\CategoryController@show')->name('category.show');

Route::get('brands/{brand}/{category?}', ['as' => 'brands.cats', 'uses' => 'Parts\BrandController@partsByBrand', function($brand = null, $category = null){}]);


Написал такой метод partsByBrand():
public function partsByBrand($brand, $category)
    {
        $brand = $this->findBrandBySlug($brand); // Получил бренд
        $parts = Part::with('categories')->where('parts.brand_id','=', $brand->id)->get(); // Получил запчасти привязанные к бренду и категорию каждой запчасти
        return $parts;
    }

Не пойму куда плясать дальше.

Я могу создать пустой массив категорий, перебрать все категории в цикле(текущих товаров и передать их во view, чтобы они открывались по такому маршруту:
Route::get('brands/{brand}/{category?}', ['as' => 'brands.cats', 'uses' => 'Parts\BrandController@partsByBrand', function($brand = null, $category = null){}]);


Далее, проверять, что если есть категория, получаю все товары, где категория и бренд равен N, но мне кажется, что это плохое решение, смущает количество запросов для вывода каталога + правильность данного решения, + как это будет работать, когда запчастей будет более 2 млн.

+ Мне по одному маршруту нужно отобразить несколько разных view, когда я сначала показываю найденные категории, а затем товары в этих категориях,
это делается просто через if() или есть решение получше?
  • Вопрос задан
  • 409 просмотров
Пригласить эксперта
Ответы на вопрос 3
solotony
@solotony
покоряю пик Балмера
используй whereHas
Ответ написан
select (*, список полей которые нужны) from categories join parts on categories.id=parts.cat_id join brands on parts.brand=brands.id where brand.title='название', categories.title='название' ну и т.д.;
Ответ написан
alexvdv
@alexvdv Автор вопроса
$parts = Part::with('categories')->where('parts.brand_id','=', $brand->id)->get(); // Получил запчасти привязанные к бренду

        foreach($parts as $part)
        {
            foreach($part->categories as $category)
            {
                // Привязываем категорию к бренду через pivot;
            }
        }


Еще вопрос, когда например мне нужен замудренный каталог или что-то не стандартное, как я выше скинул + большое количество записей, я же могу например сделать сводную таблицу pivot_brаnd_categories и в фоновом режиме, использую php workers и менеджер очередей, раз в сутки например перебирать все категории и привязывать их к бренду, и по запросу просто отдавать нужные категории, без долгих обращений к БД . На сколько это хорошее решение?

Вообщем, пока остановился на таком варианте, требуемые функции выполняет:

public function partsByBrand($brand, $category)
    {
        if(isset($category) && !empty($category))
        {
            $parts = Part::where('brand_id', '=', $brand->id)->whereHas('categories', function ($query) use ($category)
            {
                return $query->where('category_id', $category->id);
            })->get();

            return $parts;
        }

        $brand_categories = PartCategory::whereHas('parts', function($query) use ($brand)
        {
            return $query->whereHas('brand', function($query) use ($brand) {
                return $query->where('brand_id', $brand->id);
            });
        })->orderBy('created_at', 'desc')->get();

        return $brand_categories;
    }
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы