Ограничения по дополнительным свойствам в контроллерах
Контроллеры показа Informationsystem_Controller_Show, Shop_Controller_Show, Siteuser_List_Controller_Show имеют метод addFilter(), реализующий простой интерфейс указания условий фильтрации. См. Фильтр и быстрый фильтр → Применение фильтров.
Самостоятельное указание условий через QueryBuilder
Контроллеры показа позволяют влиять на отбираемые элементы, добавлять дополнительные условия и т.п. Получение объекта, которому могут быть добавлены дополнительные ограничение выборки, осуществляется различными методами, зависящими от контроллера и выбираемых элементов:
- Контроллер Informationsystem_Controller_Show
- Метод informationsystemItems() для ограничений информационных элементов.
- Промежуточная таблица для свойств informationsystem_item_properties
- Метод informationsystemGroups() для ограничений информационных групп.
- Промежуточная таблица для свойств informationsystem_group_properties
- Метод informationsystemItems() для ограничений информационных элементов.
- Контроллер Shop_Controller_Show
- Метод shopItems() для ограничений товаров.
- Промежуточная таблица для свойств shop_item_properties
- Метод shopGroups() для ограничений групп товаров.
- Промежуточная таблица для свойств shop_group_properties
- Метод shopItems() для ограничений товаров.
Рассмотрим пример ограничений выборки информационных элементов, ограничения будем добавлять с использованием QueryBuilder.
Объект получаем через
$Informationsystem_Controller_Show->informationsystemItems()
Это уже объект ORM (Core_Entity), у которого можно получить ->queryBuilder() и далее добавлять ограничения. Пример фильтрации по одному свойству одного вида (целое число):
$Informationsystem_Controller_Show = new Informationsystem_Controller_Show(
Core_Entity::factory('Informationsystem', 1)
);
$Informationsystem_Controller_Show
->xsl(
Core_Entity::factory('Xsl')->getByName('СписокНовостейНаГлавной')
)
->groupsMode('none')
->itemsForbiddenTags(array('text'))
->group(FALSE)
->limit(3)
//->show()
;
// Объединение с нужной таблицей свойств
$Informationsystem_Controller_Show
->informationsystemItems()
->queryBuilder()
->join('property_value_ints', 'informationsystem_items.id', '=', 'property_value_ints.entity_id')
// Идентификатор дополнительного свойства
->where('property_value_ints.property_id', '=', 19)
// Значение дополнительного свойства
->where('property_value_ints.value', '=', '123');
$Informationsystem_Controller_Show->show();
Обратите внимание, что сейчас значения всех доп. свойств хранятся в 6 разных таблицах:
- property_value_datetimes для даты и даты-времени;
- property_value_files для файлов;
- property_value_ints для целых чисел;
- property_value_floats для чисел с плавающей запятой;
- property_value_strings для строк;
- property_value_texts для текстов.
В примере дано ограничение и объединение по числам, если используются другие таблицы, их аналогичным образом необходимо подключить.
При работе с магазином просто заменяете informationsystem на shop, при работе с группами вместо элементов заменяете item на group.
При фильтрации по нескольким разным типам свойств в условие having необходимо подставить количество фильтруемых свойств, если фильтруете по одному свойству, то having можно опустить.
$Informationsystem_Controller_Show
->informationsystemItems()
->queryBuilder()
->leftJoin('informationsystem_item_properties', 'informationsystem_items.informationsystem_id', '=', 'informationsystem_item_properties.informationsystem_id')
// Первое свойство будет целочисленное
->leftJoin('property_value_ints', 'informationsystem_items.id', '=', 'property_value_ints.entity_id',
array(
array('AND' => array('informationsystem_item_properties.property_id', '=', Core_QueryBuilder::expression('`property_value_ints`.`property_id`')))
)
)
// Второе свойство будет вещественное
->leftJoin('property_value_floats', 'informationsystem_items.id', '=', 'property_value_floats.entity_id',
array(
array('AND' => array('informationsystem_item_properties.property_id', '=', Core_QueryBuilder::expression('`property_value_floats`.`property_id`')))
)
)
// Открываем скобку
->open()
// Идентификатор дополнительного свойства1
->where('informationsystem_item_properties.property_id', '=', 19)
// Значение дополнительного свойства1
->where('property_value_ints.value', '=', '123')
// Все варианты пар свойсвтво-значение добавляются через ИЛИ!
->setOr()
// Идентификатор дополнительного свойства2
->where('informationsystem_item_properties.property_id', '=', 17)
// Значение дополнительного свойства2
->where('property_value_floats.value', '>', 2.5)
// Закрываем скобку
->close()
->groupBy('informationsystem_items.id')
// Количество свойств у нас 2!
->having(Core_Querybuilder::expression('COUNT(DISTINCT `informationsystem_item_properties`.`property_id`)'), '=', 2);
$Informationsystem_Controller_Show->show();
Пример фильтрации структуры по одному целочисленному свойству:
$Structure_Controller_Show
->structure()
->queryBuilder()
->join('property_value_ints', 'structures.id', '=', 'property_value_ints.entity_id')
// Идентификатор дополнительного свойства
->where('property_value_ints.property_id', '=', 321)
// Значение дополнительного свойства
->where('property_value_ints.value', '=', 1);
$Structure_Controller_Show->show();
Пример фильтрации товаров с использованием псевдонимом по двум разным целочисленным свойствам 17 и 19, которые должны быть одновременно:
$Shop_Controller_Show
->shopItems()
->queryBuilder()
// Таблица property_value_ints с псевдонимом pvi1
->join(array('property_value_ints', 'pvi1'), 'shop_items.id', '=', 'pvi1.entity_id')
// Идентификатор дополнительного свойства
->where('pvi1.property_id', '=', 17)
// Значение дополнительного свойства
->where('pvi1.value', '=', '567')
// Таблица property_value_ints с псевдонимом pvi2
->join(array('property_value_ints', 'pvi2'), 'shop_items.id', '=', 'pvi2.entity_id')
// Идентификатор дополнительного свойства
->where('pvi2.property_id', '=', 19)
// Значение дополнительного свойства
->where('pvi2.value', '=', '321');
А если значения свойства может не быть?
Если допускается отсутствие значения свойства, то через ИЛИ проверяем на NULL, пример для второго свойства с кодом 17:
$Informationsystem_Controller_Show
->informationsystemItems()
->queryBuilder()
->leftJoin('informationsystem_item_properties', 'informationsystem_items.informationsystem_id', '=', 'informationsystem_item_properties.informationsystem_id')
// Первое свойство будет целочисленное
->leftJoin('property_value_ints', 'informationsystem_items.id', '=', 'property_value_ints.entity_id',
array(
array('AND' => array('informationsystem_item_properties.property_id', '=', Core_QueryBuilder::expression('`property_value_ints`.`property_id`')))
)
)
// Второе свойство будет вещественное
->leftJoin('property_value_floats', 'informationsystem_items.id', '=', 'property_value_floats.entity_id',
array(
array('AND' => array('informationsystem_item_properties.property_id', '=', Core_QueryBuilder::expression('`property_value_floats`.`property_id`')))
)
)
// Открываем скобку
->open()
// Идентификатор дополнительного свойства1
->where('informationsystem_item_properties.property_id', '=', 19)
// Значение дополнительного свойства1
->where('property_value_ints.value', '=', '123')
// Все варианты пар свойсвтво-значение добавляются через ИЛИ!
->setOr()
// Идентификатор дополнительного свойства2
->where('informationsystem_item_properties.property_id', '=', 17)
// Значение дополнительного свойства2, допускается отсутствие значения
->open()
->where('property_value_floats.value', '>', 2.5)
->setOr()
->where('property_value_floats.value', 'IS', NULL)
->close()
// Закрываем скобку
->close()
->groupBy('informationsystem_items.id')
// Количество свойств у нас 2!
->having(Core_Querybuilder::expression('COUNT(DISTINCT `informationsystem_item_properties`.`property_id`)'), '=', 2);
$Informationsystem_Controller_Show->show();