на днях доделал такой сайт. ломание головы остановилось на eav с несколькими типами полей
вот как получилось
объявления
категории объявлений
общие поля для объяв из всех категорий
свойства категорий
значения свойств для объявлений
основной косяк еава это то что невозможно выбрать одним запросом в зависимости от настроек фильтра, приходится по каждому параметру собирать айдишники и потом их интерсектить, примерно так
private function get_offers($page, $per_page)
{
$filter_fields = $this->get_current_filter_enabled_fields();
$filter_values = $this->s('@filter~:values_by_cats/' . $this->cat->id);
//
$offers_ids_sets = array();
$offers_extra_ids_sets = array();
if ($filter_values) {
foreach ($filter_values as $field_id => $data) {
if (isset($filter_fields[$field_id])) {
$field = $filter_fields[$field_id];
$prop = $field['prop'];
$common_prop = $field['common_prop'];
if ($prop) {
$type = $prop['type'];
if ($type == 'bool' && $data['value']) {
$offers_ids_sets[] = PropValue::where('prop_id', $prop['id'])
->where('bool_value', true)
->lists('offer_id')->toArray();
}
if ($type == 'strings_list' && isset($data['selected']) && !is_null($data['selected'])) {
$prop_settings = _j($prop['settings']);
if (isset($prop_settings['strings_list']['items'][$data['selected']])) {
$offers_ids_sets[] = PropValue::where('prop_id', $prop['id'])
->where('string_value', $prop_settings['strings_list']['items'][$data['selected']])
->lists('offer_id')->toArray();
}
}
if ($type == 'numbers_list' && isset($data['selected']) && !is_null($data['selected'])) {
$prop_settings = _j($prop['settings']);
if (isset($prop_settings['numbers_list']['items'][$data['selected']])) {
$offers_ids_sets[] = PropValue::where('prop_id', $prop['id'])
->where('number_value', $prop_settings['numbers_list']['items'][$data['selected']])
->lists('offer_id')->toArray();
}
}
if (($type == 'numbers_list' || $type == 'number') && isset($data['min']) && isset($data['max'])) {
$offers_ids_sets[] = PropValue::where('prop_id', $prop['id'])
->where('number_value', '>=', $data['min'])
->where('number_value', '<=', $data['max'])
->lists('offer_id')->toArray();
}
}
if ($common_prop) {
$type = $common_prop['type'];
if (($type == 'numbers_list' || $type == 'number') && isset($data['min']) && isset($data['max'])) {
$offers_ids_sets[] = OfferExtra
::where($common_prop['field'], '>=', $data['min'])
->where($common_prop['field'], '<=', $data['max'])
->lists('offer_id')->toArray();
}
}
}
}
}
$offers_ids = array();
if ($offers_ids_sets) {
$offers_ids = (array)$offers_ids_sets[0];
for ($i = 1; $i < count($offers_ids_sets); $i++) {
$offers_ids = array_intersect($offers_ids, (array)$offers_ids_sets[$i]);
}
}
//
$builder = $this->cat->offers();
if ($offers_ids_sets) {
$builder = $builder->whereIn('id', $offers_ids);
}
$builder = $builder->whereHas('extra', function ($builder) use ($offers_extra_ids_sets) {
$builder->where('enabled', true);
});
$count = $builder->count();
$offers = $builder->orderBy('created_at', 'DESC')->offset(($page - 1) * $per_page)->take($per_page)->get();
return array($count, $offers);
}
и вообще никак невозможно сортировать по параметрам, если нужна сортировка по какому-то параметру придется переносить ее в таблицу товаров самих
но все равно по гибкости он выигрывает у остальных вариантов. клиент сам через интерфейс может рулить своими категориями свойствами и тд. если бы была таблица в которой всё, она бы вешалась при каждой такой операции, на время пропорциональное кол-ву товаров