Для вывода товаров из подгрупп достаточно указать контроллеру опцию ->subgroups(TRUE)
$Shop_Controller_Show->subgroups(TRUE);
Использование subgroups(TRUE) доступно при указании в group() идентификатора родительской группы, если в group() будет указан массив, subgroups(TRUE) не будет иметь действия.
В коде настроек типовой динамической страницы интернет-магазина объявим Hostcms_Subgroups и через метод fillShopGroup() будем получать все подгруппы заданной группы. Затем после parseUrl() проверим, в какой группе находимся, если в корневой, то установим ->group(FALSE), чтобы выборка шла без учета групп, если же внутри определенной группы, то выберем подгруппы этой группы в массив и передадим массив контроллеру показа в ->group.
class Hostcms_Subgroups { protected $_aGroupTree = array(); public function fillShopGroup($iShopId, $iShopGroupParentId = 0, $iLevel = 0) { $iShopId = intval($iShopId); $iShopGroupParentId = intval($iShopGroupParentId); $iLevel = intval($iLevel); if ($iLevel == 0) { $aTmp = Core_QueryBuilder::select('id', 'parent_id') ->from('shop_groups') ->where('shop_id', '=', $iShopId) ->where('deleted', '=', 0) ->execute()->asAssoc()->result(); foreach ($aTmp as $aGroup) { $this->_aGroupTree[$aGroup['parent_id']][] = $aGroup; } } $aReturn = array(); if (isset($this->_aGroupTree[$iShopGroupParentId])) { foreach ($this->_aGroupTree[$iShopGroupParentId] as $childrenGroup) { $aReturn[] = $childrenGroup['id']; $aReturn = array_merge($aReturn, $this->fillShopGroup($iShopId, $childrenGroup['id'], $iLevel + 1)); } } $iLevel == 0 && $this->_aGroupTree = array(); return $aReturn; } } // ... // Root group if ($Shop_Controller_Show->group == 0) { $Shop_Controller_Show->group(FALSE); } else { // Get all subgroups $oHostcms_Subgroups = new Hostcms_Subgroups(); $aSubGroupsID = $oHostcms_Subgroups->fillShopGroup($oShop->id, $Shop_Controller_Show->group); // Set first ID as current group array_unshift($aSubGroupsID, $Shop_Controller_Show->group); $Shop_Controller_Show->group = $aSubGroupsID; }
Вывод товаров из текущей группы и всех ее подгрупп требует замены некоторых методов контроллера показа, для этого в типовой динамической странице интернет-магазина унаследуем контроллер показа и переопределим несколько методов.
class My_Shop_Controller_Show extends Shop_Controller_Show { protected function _groupCondition() { $oShop = $this->getEntity(); if ($this->parentItem == 0) { // Отключаем выбор модификаций //!$this->_selectModifications && $this->forbidSelectModifications(); $this->shopItems() ->queryBuilder() ->open(); if ($this->group) { // если ID группы не 0, т.е. не корневая группа // получаем подгруппы $aSubGroupsID = $this->fillShopGroup($oShop->id, $this->group); // добавляем текущую группу в массив $aSubGroupsID[] = $this->group; $this->shopItems() ->queryBuilder() // получаем все товары из подгрупп ->where('shop_items.shop_group_id', 'IN', $aSubGroupsID); } else { $this->shopItems() ->queryBuilder() ->where('shop_items.modification_id', '=', 0); /*$this->shopItems() ->queryBuilder() ->where('shop_items.shop_group_id', '=', 0) ;*/ } $shop_group_id = !$this->parentItem ? intval($this->group) : 0; // Вывод модификаций на одном уровне в списке товаров if (!$this->item && $this->modificationsList) { $oCore_QueryBuilder_Select_Modifications = Core_QueryBuilder::select('shop_items.id') ->from('shop_items') ->where('shop_items.shop_id', '=', $oShop->id) ->where('shop_items.deleted', '=', 0) ->where('shop_items.active', '=', 1); if ($this->group) { $oCore_QueryBuilder_Select_Modifications ->where('shop_items.shop_group_id', 'IN', $aSubGroupsID); // получаем все товары из подгрупп } // Стандартные ограничения для товаров $this->_applyItemConditionsQueryBuilder($oCore_QueryBuilder_Select_Modifications); Core_Event::notify(get_class($this) . '.onBeforeSelectModifications', $this, array($oCore_QueryBuilder_Select_Modifications)); $this->_Shop_Items ->queryBuilder() ->setOr() ->where('shop_items.shop_group_id', '=', 0) ->where('shop_items.modification_id', 'IN', $oCore_QueryBuilder_Select_Modifications); // Совместное modificationsList + filterShortcuts if ($this->filterShortcuts) { $oCore_QueryBuilder_Select_Shortcuts_For_Modifications = Core_QueryBuilder::select('shop_items.shortcut_id') ->from('shop_items') ->where('shop_items.shop_id', '=', $oShop->id) ->where('shop_items.deleted', '=', 0) ->where('shop_items.active', '=', 1) ->where('shop_items.shop_group_id', '=', $shop_group_id) ->where('shop_items.shortcut_id', '>', 0); $this->_Shop_Items ->queryBuilder() ->setOr() ->where('shop_items.shop_group_id', '=', 0) ->where('shop_items.modification_id', 'IN', $oCore_QueryBuilder_Select_Shortcuts_For_Modifications); } } if ($this->filterShortcuts) { $oCore_QueryBuilder_Select_Shortcuts = Core_QueryBuilder::select('shop_items.shortcut_id') ->from('shop_items') ->where('shop_items.deleted', '=', 0) ->where('shop_items.active', '=', 1) ->where('shop_items.shop_group_id', '=', $shop_group_id) ->where('shop_items.shortcut_id', '>', 0); // Стандартные ограничения для товаров $this->_applyItemConditionsQueryBuilder($oCore_QueryBuilder_Select_Shortcuts); $this->_Shop_Items ->queryBuilder() ->setOr() ->where('shop_items.id', 'IN', $oCore_QueryBuilder_Select_Shortcuts); } $this->_Shop_Items ->queryBuilder() ->close(); } else { parent::_groupCondition(); } return $this; } protected $_aGroupTree = array(); public function fillShopGroup($iShopId, $iShopGroupParentId = 0, $iLevel = 0) { $iShopId = intval($iShopId); $iShopGroupParentId = intval($iShopGroupParentId); $iLevel = intval($iLevel); if ($iLevel == 0) { $aTmp = Core_QueryBuilder::select('id', 'parent_id') ->from('shop_groups') ->where('shop_id', '=', $iShopId) ->where('deleted', '=', 0) ->execute()->asAssoc()->result(); foreach ($aTmp as $aGroup) { $this->_aGroupTree[$aGroup['parent_id']][] = $aGroup; } } $aReturn = array(); if (isset($this->_aGroupTree[$iShopGroupParentId])) { foreach ($this->_aGroupTree[$iShopGroupParentId] as $childrenGroup) { $aReturn[] = $childrenGroup['id']; $aReturn = array_merge($aReturn, $this->fillShopGroup($iShopId, $childrenGroup['id'], $iLevel + 1)); } } $iLevel == 0 && $this->_aGroupTree = array(); return $aReturn; } }
Код класса добавляется в настройки типовой динамической страницы магазина перед:
$Shop_Controller_Show = new Shop_Controller_Show($oShop);
Сама строка
$Shop_Controller_Show = new Shop_Controller_Show($oShop);
заменяется на
$Shop_Controller_Show = new My_Shop_Controller_Show($oShop);
есть строка // получаем все товары из подгрупп ->where('shop_items.shop_group_id', 'IN', $aSubGroupsID); А как подсчитать эти найденные товары? Мне надо для условия, если их меньше 3, то рандомно прибавляем вывод еще из другой группы.
До выполнения метода ->show() количество товаров не сможет быть подсчитано, после получить массив с идентификаторами показанных товаров можно методом getShownIDs()
Фильтр корректно работает только если находишься в последней подгруппе!
Как исправить?
В макете где вызывается фильтр надо исправить Shop_Controller_Show на My_Shop_Controller_Show