Задумал я сделать фильтры с параметрами. Но это не магазин, а просто портал с новостями, постами которые будут привязываться к этим параметрам. Подбор будет происходить через get запрос, потому для красивых ссылок будем передавать не id параметров(что конечно было бы намного проще), а названия параметров Схема условно вот такая - некоторые не важные, на данный момент, поля убрал для читаемости: PHP: class Filter extends Model { protected $fillable = [ 'name', 'slug', ]; } class FilterOption extends Model { protected $fillable = [ 'filter_id', 'value'//Название параметра ]; } class FilterOptionRelation extends Model { protected $fillable = [ 'model_type', //Здесь хранится модель в виде строки, например App\Models\Post 'model_id', //а здесь id модели 'option_id', ]; } и вот у нас контроллер в котором происходит поиск по названию опции, а не по ее id. в данном случае я решил сделать посадочную страницу для страницы с параметром Город, потому параметр запроса нам заранее известен. PHP: $result = FilterOption::where('value, $request->city_name) ->with('filter_option_relation')//Делаю жадную загрузку ->first(); Вот метод для жадной загрузки PHP: class FilterOption extends Model { public function filter_option_relation(){ return $this->hasMany('App\Models\FilterOptionRelation', 'option_id', 'id'); } } Теперь в модели создаем метод подтягивания модели исходя из поля model_type PHP: class FilterOptionRelation extends Model { public function model_data(){ return $this->belongsTo($this->model_type, 'model_id', 'id'); } } и уже в контроллере или в шаблоне blade мы можем обратиться к модели PHP: foreach ($result->filter_option_relation as $options){ echo $options->model_data->name; } подскажите перемудрил или недомудрил и можно сделать оптимальнее? хотелось бы для развития понимания делать правильно. заранее спасибо.
Ах да, забыл, не могу пока никак найти, каким образом при вызове ->with('filter_option_relation') передать еще параметр для выборки определенной модели
итак, после более глубокого изучения доки я переделал свою выборку. однако сталкиваюсь с проблемой - как выбрать из базы данные которые строго подходят под все параметры из массива whereIn, а не выбираются все т.е. о чем это я снова имеем три таблицы Posts FilterOptions FilterOptionRelations понятно что в таблице FilterOptions хранятся опции например id, slug 1, minsk 2, moskva 3, washington понятно что в таблице FilterOptionRelations хранятся связи например model_type, model_id, option_id App\Post, 1, 1 App\Post, 1, 3 App\Post, 3, 1 PHP: //Здесь у нас связь public function filter_options() { return $this->morphToMany('App\Models\FilterOption', 'filter_option_relation'); } Выбираю c параметром slug - minsk PHP: Post::whereHas('filter_options', function ($query){ return $query->whereIn('filter_options.slug', ['minsk']); }); Получаю коллекцию с двумя постами, в данном случае все верно. Теперь выбираю c параметром slug - ['minsk', 'washington'] PHP: Post::whereHas('filter_options', function ($query){ return $query->whereIn('filter_options.slug',['minsk', 'washington']); }); И получаю снова два поста, т.к. к одному и второму подошел slug - minsk А хочу получить только один пост, к которому подходят оба параметра minsk и washington, а пост которому подходит только minsk - отбросить. вроде уже вдоль и поперек перелистал доку и примеров в гугле не нашел.
В этом случае надо использовать цепочку where(), а не whereIn(). Подробнее, в пункте "Сложная фильтрация (WHERE)"
Можно усилить ограничения добавлением группировки (group by) и сравнением (having) количества полученных совпадений с количеством элементов массива.
да, так и сделал. PHP: $filterOptions = ['minsk', 'moskva']; Post::whereHas('filter_options', function ($query) use ($filterOptions){ return $query->whereIn('filter_options.slug', $filterOptions); }, '=', count($filterOptions) ) ->where('enabled', true)