Хочу предложить вам одну полезную доработку, которая поможет вам показывать в карточке товара другие продукты, схожие по цене или какому-то свойству, а может быть и по всем свойствам. Это будет способствовать тому, что Покупатель просмотрит большее количество товаров на вашем сайте и увеличит шанс на совершение им покупки. Поэтому рекомендую взять на вооружение.
Зайдём в Дополнительные свойства для групп товаров и создадим раздел, который назовём "Управление похожими товарами".

В данном разделе создадим Допсвойство "Отбирать по всем признакам" (флажок, cs_show_all) и "Отбирать по цене" (флажок, cs_show_price), а также создадим, к примеру, два Раздела для отбора по каким-то свойствам из ваших товаров - "Свойство №1" и "Свойство №2". Внутри каждого раздела создадим два Допсвойства - "ID свойства" (целое число, cs_id_p1 и cs_id_p2) и "Отбирать по этому свойству" (флажок, cs_show_p1 и cs_show_p2).



После этого, если зайти в настройки группы товаров, во вкладке "Дополнительные свойства" у нас появится блок "Управление похожими товарами".

Здесь вы можете указать ID свойства по которому отбирать Похожие товары (не забудьте, при этом, включить флажок "Отбирать по этому свойству"), включить флажок для отбора по цене или по всем свойствам. Таким образом вы создадите запросы к базе данных, по каким признакам отбирать Похожие товары в продуктах данной группы.
Далее открываем для редактрования код ТДС интернет-магазина и добавляем нижеприведённый код
if ($Shop_Controller_Show->item)
{
// управление Похожими товарами
$oShop = $Shop_Controller_Show->getEntity();
$linkedObject = Core_Entity::factory('Shop_Group_Property_List', $oShop->id);
// Массив свойств
$aProperties = $linkedObject->Properties->findAll();
foreach($aProperties as $oProperty)
{
if(strpos($oProperty->tag_name, 'cs_') !== false)
{
// собираем значения
switch($oProperty->tag_name)
{
case 'cs_id_p1':
$aPropertyValues = $oProperty->getValues($Shop_Controller_Show->group);
$cs_id_p1 = isset($aPropertyValues[0]) ? intval($aPropertyValues[0]->value) : 0;
break;
case 'cs_id_p2':
$aPropertyValues = $oProperty->getValues($Shop_Controller_Show->group);
$cs_id_p2 = isset($aPropertyValues[0]) ? intval($aPropertyValues[0]->value) : 0;
break;
case 'cs_show_price':
$aPropertyValues = $oProperty->getValues($Shop_Controller_Show->group);
$cs_show_price = isset($aPropertyValues[0]) ? intval($aPropertyValues[0]->value) : 0;
break;
case 'cs_show_p1':
$aPropertyValues = $oProperty->getValues($Shop_Controller_Show->group);
$cs_show_p1 = isset($aPropertyValues[0]) ? intval($aPropertyValues[0]->value) : 0;
break;
case 'cs_show_p2':
$aPropertyValues = $oProperty->getValues($Shop_Controller_Show->group);
$cs_show_p2 = isset($aPropertyValues[0]) ? intval($aPropertyValues[0]->value) : 0;
break;
case 'cs_show_all':
$aPropertyValues = $oProperty->getValues($Shop_Controller_Show->group);
$cs_show_all = isset($aPropertyValues[0]) ? intval($aPropertyValues[0]->value) : 0;
break;
}
}
}
// начинаем делать выборку товаров по определенным параметрам
// по цене (без учета скидок)
$oCurrentShop_Item = Core_Entity::factory('Shop_Item', $Shop_Controller_Show->item);
if($cs_show_price)
{
$oXmlEntity = Core::factory('Core_Xml_Entity')->name('same_by_price');
$Shop_Controller_Show->addEntity($oXmlEntity);
$oShop_Items = Core_Entity::factory('Shop_Item', $Shop_Controller_Show->item)->Shop_Group->Shop_Items;
$oShop_Items->queryBuilder()
->where('shop_items.price', '>=', $oCurrentShop_Item->price)
->where('shop_items.price', '<=', ($oCurrentShop_Item->price + $oCurrentShop_Item->price*0.2))
->where('shop_items.id', '!=', $oCurrentShop_Item->id)
->clearOrderBy()
->orderBy('shop_items.price', 'ASC')
->limit(4)
;
$aShop_Items = $oShop_Items->findAll();
foreach($aShop_Items as $oShop_Item)
{
$oXmlEntity->addEntity($oShop_Item);
}
}
// по свойству 1
if($cs_show_p1 && $cs_id_p1)
{
$oProperty = Core_Entity::factory('Property', $cs_id_p1);
$aPropertyValues = $oProperty->getValues($oCurrentShop_Item->id);
$cs_val_p1 = isset($aPropertyValues[0]) ? intval($aPropertyValues[0]->value) : 0;
if($cs_val_p1)
{
$oXmlEntity = Core::factory('Core_Xml_Entity')->name('same_by_p1')->addAttribute('property_name', $oProperty->name);
$Shop_Controller_Show->addEntity($oXmlEntity);
$oShop_Items = Core_Entity::factory('Shop_Item', $Shop_Controller_Show->item)->Shop_Group->Shop_Items;
$oShop_Items->queryBuilder()
->select('shop_items.*')
->leftJoin('property_value_ints', 'property_value_ints.entity_id', '=', 'shop_items.id')
->where('property_value_ints.property_id', '=', $cs_id_p1)
->where('property_value_ints.value', '>=', $cs_val_p1)
->where('property_value_ints.value', '<=', ($cs_val_p1 + $cs_val_p1*0.2))
->where('shop_items.id', '!=', $oCurrentShop_Item->id)
->clearOrderBy()
->orderBy('property_value_ints.value', 'ASC')
->limit(4)
;
$aShop_Items = $oShop_Items->findAll();
foreach($aShop_Items as $oShop_Item)
{
$oXmlEntity->addEntity($oShop_Item);
}
}
}
// по свойству 2
if($cs_show_p2 && $cs_id_p2)
{
$oProperty = Core_Entity::factory('Property', $cs_id_p2);
$aPropertyValues = $oProperty->getValues($oCurrentShop_Item->id);
$cs_val_p2 = isset($aPropertyValues[0]) ? intval($aPropertyValues[0]->value) : 0;
if($cs_val_p2)
{
$oXmlEntity = Core::factory('Core_Xml_Entity')->name('same_by_p2')->addAttribute('property_name', $oProperty->name);
$Shop_Controller_Show->addEntity($oXmlEntity);
$oShop_Items = Core_Entity::factory('Shop_Item', $Shop_Controller_Show->item)->Shop_Group->Shop_Items;
$oShop_Items->queryBuilder()
->select('shop_items.*')
->leftJoin('property_value_ints', 'property_value_ints.entity_id', '=', 'shop_items.id')
->where('property_value_ints.property_id', '=', $cs_id_p2)
->where('property_value_ints.value', '>=', $cs_val_p2)
->where('property_value_ints.value', '<=', ($cs_val_p2 + $cs_val_p2*0.2))
->where('shop_items.id', '!=', $oCurrentShop_Item->id)
->clearOrderBy()
->orderBy('property_value_ints.value', 'ASC')
->limit(4)
;
$aShop_Items = $oShop_Items->findAll();
foreach($aShop_Items as $oShop_Item)
{
$oXmlEntity->addEntity($oShop_Item);
}
}
}
// по всем свойствам сразу (точное совпадение)
if($cs_show_all && $cs_id_p1 && $cs_id_p2)
{
$oProperty = Core_Entity::factory('Property', $cs_id_p1);
$aPropertyValues = $oProperty->getValues($oCurrentShop_Item->id);
$cs_val_p1 = isset($aPropertyValues[0]) ? intval($aPropertyValues[0]->value) : 0;
$oProperty = Core_Entity::factory('Property', $cs_id_p2);
$aPropertyValues = $oProperty->getValues($oCurrentShop_Item->id);
$cs_val_p2 = isset($aPropertyValues[0]) ? intval($aPropertyValues[0]->value) : 0;
if($cs_val_p1 && $cs_val_p2)
{
$oXmlEntity = Core::factory('Core_Xml_Entity')->name('same_by_all');
$Shop_Controller_Show->addEntity($oXmlEntity);
$oShop_Items = Core_Entity::factory('Shop_Item', $Shop_Controller_Show->item)->Shop_Group->Shop_Items;
$oShop_Items->queryBuilder()
->select('shop_items.*')
->leftJoin('property_value_ints', 'property_value_ints.entity_id', '=', 'shop_items.id')
->where('property_value_ints.property_id', '=', $cs_id_p1)
->where('property_value_ints.value', '=', $cs_val_p1)
->where('shop_items.price', '=', $oCurrentShop_Item->price)
->where('shop_items.id', '!=', $oCurrentShop_Item->id)
->clearOrderBy()
->orderBy('RAND()')
->limit(4)
;
$aShop_Items = $oShop_Items->findAll();
foreach($aShop_Items as $oShop_Item)
{
$oXmlEntity->addEntity($oShop_Item);
}
$oShop_Items = Core_Entity::factory('Shop_Item', $Shop_Controller_Show->item)->Shop_Group->Shop_Items;
$oShop_Items->queryBuilder()
->select('shop_items.*')
->leftJoin('property_value_ints', 'property_value_ints.entity_id', '=', 'shop_items.id')
->where('property_value_ints.property_id', '=', $cs_id_p2)
->where('property_value_ints.value', '=', $cs_val_p2)
->where('shop_items.price', '=', $oCurrentShop_Item->price)
->where('shop_items.id', '!=', $oCurrentShop_Item->id)
->clearOrderBy()
->orderBy('RAND()')
->limit(4)
;
$aShop_Items = $oShop_Items->findAll();
foreach($aShop_Items as $oShop_Item)
{
$oXmlEntity->addEntity($oShop_Item);
}
}
}
}
В итоге, в XML карточки товара у нас попадут Похожие товары, отобранные по заданным в настройках группы признакам, которые будут находиться в соответствующих тегах:
<same_by_price>
<same_by_all>
<same_by_p1>
<same_by_p2>
Далее, в XSL шаблоне Карточки товара вы можете использовать данные из XML по своему усмотрению
Для примера:
<xsl:template match="shop_item">
.....................
Здесь ваш код
.....................
<xsl:if test="/shop/*[starts-with(name(), 'same_')]/shop_item">
<div class="same-items">
<xsl:if test="/shop/same_by_all/shop_item">
<h4>С такими же характеристиками</h4>
<div class="row">
<xsl:apply-templates select="/shop/same_by_all/shop_item" mode="same-items"/>
</div>
</xsl:if>
<xsl:if test="/shop/same_by_price/shop_item">
<h4>Со схожей ценой</h4>
<div class="row">
<xsl:apply-templates select="/shop/same_by_price/shop_item" mode="same-items"/>
</div>
</xsl:if>
<xsl:if test="/shop/same_by_p1/shop_item">
<h4>Совпадает <!-- Здесь будет выводиться название свойства--><xsl:value-of disable-output-escaping="yes" select="/shop/same_by_p1/@property_name"/></h4>
<div class="row">
<xsl:apply-templates select="/shop/same_by_p1/shop_item" mode="same-items"/>
</div>
</xsl:if>
<xsl:if test="/shop/same_by_p2/shop_item">
<h4>Совпадает <!-- Здесь будет выводиться название свойства--><xsl:value-of disable-output-escaping="yes" select="/shop/same_by_p2/@property_name"/></h4>
<div class="row">
<xsl:apply-templates select="/shop/same_by_p2/shop_item" mode="same-items"/>
</div>
</xsl:if>
</div>
</xsl:if>
</xsl:template>
<!-- Шаблон для схожих товаров -->
<xsl:template match="shop_item" mode="same-items">
<div class="col-12 col-sm-6 col-md-4 col-lg-3">
<div class="product">
.....................
Здесь ваш код карточки товара
.....................
</div>
</div>
</xsl:template>
Данное решение работает с обновлением 7.8 и более ранними.
К сожалению, автор мне не известен.