Форум пользователей Impera CMS
Impera CMS - отличный движок для лёгкого создания интернет магазина.
Обладает невероятным количеством функций, необходимых в онлайн торговле.

Следить
Главная
13:24
03 сен
#
?
написал:

Делюсь решением, может кому-нибудь пригодится. Делал для магазина we-pool.ru.

Решение основано на модификации старой версии шаблона Electronics, для новой надо менять пути и имена файлов модулей.

Могу сделать и вам, не бесплатно конечно. Обращайтесь в скайп cravciucandy.

Задача: В правой колонке есть сквозной блок "Специальные предложения" с jQuery ротацией товаров. Туда нужно вывести 25 акционных товаров и 25 хитов продаж, перемешав случайным образом этот объединенный список.

Проблема: В стандартной Impera CMS списки акционных товаров и хитов продаж доступны только на главной и страницах категорий. Следовательно в хелпер шаблона - файл шаблон/html/emulator.php - надо добавить свои функции чтения акционных и хитов - actionProducts и hitProducts, а также зарегистрировать их в хелпере шаблона.

Я сделал двойной копипаст готовой функции из стандартного хелпера, назвав дубли нужными именами и сменив один параметр в каждом копипасте. Вот что получилось:

<?php
    class TemplateEmulator {
        ...
        ...

        // ===================================================================
        /**
        *  Подключение наших функций и модификаторов в шаблонизатор Smarty
        *
        *  -------------------------------------------------------------------
        *
        *  @access  protected
        *  @param   object  $cms        объект движка
        *  @return  void
        */
        // ===================================================================

        protected function setSmartyPlugins ( & $cms ) {
            ...
            ...
            // регистрируем свои функции
            $cms->smarty->registerPlugin('function', 'actionProducts', array($this, 'actionProducts'));
            $cms->smarty->registerPlugin('function', 'hitProducts', array($this, 'hitProducts'));
        }

        // ===================================================================
        /**
        *  Обработчик шаблонизационной функции actionProducts
        *
        *  -------------------------------------------------------------------
        *
        *  @access  public
        *  @param   array   $params     массив параметров, указанных в вызове:
        *                                   ['var'] = в какую переменную возвратить результат
        *                                   ['count'] = число записей на странице (по умолчанию 12)
        *                                   ['page'] = номер текущей страницы (по умолчанию 1)
        *  @param   object  $smarty     объект шаблонизатора Smarty
        *  @return  string              всегда пустая строка
        */
        // ===================================================================

        public function actionProducts ( $params = null, & $smarty = null ) {

            // проверяем наличие обязательного параметра
            $field = 'var';
            if (isset($params[$field]) && is_string($params[$field]) && $params[$field] != '') {

                // опциональные праметры
                $count = 'count';
                $count = isset($params[$count]) ? max(1, @ intval($params[$count])) : 12;

                $page = 'page';
                $page = isset($params[$page]) ? max(1, @ intval($params[$page])) : 1;

                // текущий пользователь, если есть
                $user = null;
                if (isset($this->cms->user)) $user = & $this->cms->user;

                // настраиваем фильтр записей
                $filter = new stdClass;

                    // только акционные
                    $filter->type = TYPE_PRODUCTS_ACTIONAL;

                    // только разрешенные к показу
                    $filter->enabled = 1;

                    // если это обычный посетитель, тогда только не скрытые от неавторизованных
                    if (!isset($user->user_id)) $filter->hidden = 0;

                    // упорядочить список по убыванию веса "как расставлены"
                    $filter->sort_direction = SORT_DIRECTION_DESCENDING;

                    // процент скидки пользователя и его ценовая группа
                    $filter->discount = isset($user->discount) ? $user->discount : 0;
                    $filter->price_id = isset($user->price_id) ? $user->price_id : 0;

                    // интересует список начиная с такой позиции и столько записей
                    $filter->start = ($page - 1) * $count;
                    $filter->maxcount = $count;

                // читаем список товаров
                $items = array();
                $this->cms->db->products->get($items, $filter);
                $this->cms->db->products->unpack_records($items, $filter);

                // передаем в указанную переменную
                if (!is_object($smarty)) return $items;
                $smarty->assignByRef($params[$field], $items);
            }
            return '';
        }

        // ===================================================================
        /**
        *  Обработчик шаблонизационной функции hitProducts
        *
        *  -------------------------------------------------------------------
        *
        *  @access  public
        *  @param   array   $params     массив параметров, указанных в вызове:
        *                                   ['var'] = в какую переменную возвратить результат
        *                                   ['count'] = число записей на странице (по умолчанию 12)
        *                                   ['page'] = номер текущей страницы (по умолчанию 1)
        *  @param   object  $smarty     объект шаблонизатора Smarty
        *  @return  string              всегда пустая строка
        */
        // ===================================================================

        public function hitProducts ( $params = null, & $smarty = null ) {

            // проверяем наличие обязательного параметра
            $field = 'var';
            if (isset($params[$field]) && is_string($params[$field]) && $params[$field] != '') {

                // опциональные праметры
                $count = 'count';
                $count = isset($params[$count]) ? max(1, @ intval($params[$count])) : 12;

                $page = 'page';
                $page = isset($params[$page]) ? max(1, @ intval($params[$page])) : 1;

                // текущий пользователь, если есть
                $user = null;
                if (isset($this->cms->user)) $user = & $this->cms->user;

                // настраиваем фильтр записей
                $filter = new stdClass;

                    // только хиты продаж
                    $filter->type = TYPE_PRODUCTS_HIT;

                    // только разрешенные к показу
                    $filter->enabled = 1;

                    // если это обычный посетитель, тогда только не скрытые от неавторизованных
                    if (!isset($user->user_id)) $filter->hidden = 0;

                    // упорядочить список по убыванию веса "как расставлены"
                    $filter->sort_direction = SORT_DIRECTION_DESCENDING;

                    // процент скидки пользователя и его ценовая группа
                    $filter->discount = isset($user->discount) ? $user->discount : 0;
                    $filter->price_id = isset($user->price_id) ? $user->price_id : 0;

                    // интересует список начиная с такой позиции и столько записей
                    $filter->start = ($page - 1) * $count;
                    $filter->maxcount = $count;

                // читаем список товаров
                $items = array();
                $this->cms->db->products->get($items, $filter);
                $this->cms->db->products->unpack_records($items, $filter);

                // передаем в указанную переменную
                if (!is_object($smarty)) return $items;
                $smarty->assignByRef($params[$field], $items);
            }
            return '';
        }

        ...
        ...
    }
?>

От разработчика: Идеальным решением было бы создать один копипаст, назвав эту функцию например featuredProducts, а параметр type задавать из шаблона при вызове функции, что позволило бы использовать всего лишь одну функцию для чтения новинок, хитов, акционных, обсуждаемых, ожидаемых товаров и так далее. Для задания типа читаемых записей в этом случае можно было бы использовать следующие константы:
TYPE_PRODUCTS_ORDERED - недавно покупавшиеся товары
TYPE_PRODUCTS_COMMENTED - недавно обсуждавшиеся товары
TYPE_PRODUCTS_HIT - хиты продаж (у которых включен такой флажок)
TYPE_PRODUCTS_NEWEST - новинки (у которых включен такой флажок)
TYPE_PRODUCTS_NEWEST_MIXED - новинки вперемешку с недавно добавленными
TYPE_PRODUCTS_ACTIONAL - акционные (у которых включен такой флажок или такая цена)
TYPE_PRODUCTS_DISCOUNTED - товары со скидками (без учета флажка "акционный")
TYPE_PRODUCTS_AWAITED - товары, скоро ожидаемые в продаже (у которых такой флажок)
TYPE_PRODUCTS_NONUSABLE - товары не для продажи (экспонаты)
TYPE_PRODUCTS_DOMAINED - товары, размещенные на своем субдомене
TYPE_PRODUCTS_TEMPLATED - товары, изображаемые своим шаблоном (landing page)
TYPE_PRODUCTS_CANONIZED - с канонизацией главного (разновидности главного товара)

тогда в шаблоне эта единая функция вызывалась бы следующим образом, допустим в переменную $result хотим прочесть 15 хитов продаж со 2 страницы этого воображаемого списка
{featuredProducts var=result count=15 type=$smarty.const.TYPE_PRODUCTS_HIT page=2}


Теперь надо дополнить модуль вывода "Специальные предложения" чтением акционных и хитов и смешиванием их в одном списке. В старой версии Electronics модуль находится в файле шаблон/html/right/featured.htm. Я дополнил модуль так:

{* <!-- правая колонка: товары (акционные) --> *}{strip}

    {* <!-- читаем 25 акционных товаров в переменную $actions --> *}
    {actionProducts var=actions count=25}

    {* <!-- сносим акционные в переменную $items --> *}
    {$items = []}
    {$maxcount = 50}
    {$i = 0}
    {if !empty($actions)}
        {foreach $actions as $tovar}
            {$items[$i] = $tovar}
            {$i = $i +  1}
            {if $i >= $maxcount}
                {break}
            {/if}
        {/foreach}
    {/if}

    {* <!-- читаем 25 хитов продаж в переменную $actions --> *}
    {if $i < $maxcount}
        {hitProducts var=actions count=25}

        {* <!-- подмешиваем хиты продаж в объединенный список --> *}
        {if !empty($actions)}
            {foreach $actions as $tovar}
                {$items[$i] = $tovar}
                {$i = $i +  1}
                {if $i >= $maxcount}
                    {break}
                {/if}
            {/foreach}
        {/if}
    {/if}

    {* <!-- перемешиваем объединенный список товаров случайным образом --> *}
    {(shuffle($items)) ? '' : ''}

    {* <!-- выводим --> *}
    {include file = 'center/featured.htm'
             items = $items
             maxcount = $maxcount
             title_link = ''
                 title = 'Специальное предложение'
             with_scroller = true}
{/strip}

Вот и все.

17:33
03 сен
#
?
написал:

Мне понравилась фишка с featuredProducts, так проще.

Я б ещё добавил в хэлпер функцию mixItems и естесно зарегал.
И числа 25 заменил бы настройками админки. Вдруг завтра нужно уже по 30 товаров.
В админке это легко изменить, чем искать в шаблоне.
Тогда модуль Андрея станет юзабельней. Зацените.

{* <!-- правая колонка: товары (акционные) --> *}{strip}

    {$count1 = $settings->products_actional_maxcount}
    {$count2 = $settings->products_hit_maxcount}
    {$maxcount = $count1 + $count2}

    {actionProducts count=$count1 var=actions}
    {mixItems max=$maxcount from=[$actions] var=items}
    {if count($items) < $maxcount}
        {hitProducts count=$count2 var=actions}
        {mixItems max=$maxcount from=[$items, $actions] var=items}
    {/if}

    {(shuffle($items)) ? '' : ''}

    {* <!-- выводим --> *}
    {include file = 'center/featured.htm'
             items = $items
             maxcount = $maxcount
             title_link = ''
                 title = 'Специальное предложение'
             with_scroller = true}
{/strip}

Как регать mixItems пропускаю, смотрите выше как регает функции Андрей.
Пишу только код mixItems. Эта фугкция подмешивает массив товаров к другому массиву товаров.

        // ===================================================================
        /**
        *  Обработчик шаблонизационной функции mixItems
        *
        *  -------------------------------------------------------------------
        *
        *  @access  public
        *  @param   array   $params     массив параметров, указанных в вызове:
        *                                   ['var'] = в какую переменную возвратить результат
        *                                   ['max'] = предельное число записей в миксе (по умолчанию 50)
        *                                   ['from'] = массив смешиваемых массивов (по умолчанию пустой массив)
        *  @param   object  $smarty     объект шаблонизатора Smarty
        *  @return  string              всегда пустая строка
        */
        // ===================================================================

        public function mixItems ( $params = null, & $smarty = null ) {

            // проверяем наличие обязательного параметра
            $field = 'var';
            if (isset($params[$field]) && is_string($params[$field]) && $params[$field] != '') {

                // опциональные праметры
                $from = 'from';
                $from = !empty($params[$from]) && is_array($params[$from]) ? $params[$from] : array();

                $max = 'max';
                $max = isset($params[$max]) ? max(1, @ intval($params[$max])) : 50;

                // смешиваем в порядке, как были перечислены в from
                $items = array();
                foreach ($from as & $list) {
                    if (!empty($list) && is_array($list)) {
                        foreach ($list as $item) {
                            $items[] = $item;
                            $max--;
                            if (empty($max)) break;
                        }
                        if (empty($max)) break;
                    }
                }

                // передаем в указанную переменную
                if (!is_object($smarty)) return $items;
                $smarty->assignByRef($params[$field], $items);
            }
            return '';
        }

Короче то что делал Андрей в шаблоне, но теперь в хэлпере на php.

От разработчика: Я позволил себе откомментировать ваш код и записать его в стиле Impera CMS - пусть чуть сложнее, зато с необходимыми проверками.

11:24
04 сен
#
?
написал:
Сергей написал: И числа 25 заменил бы настройками админки. Вдруг завтра нужно уже по 30 товаров.
В админке это легко изменить, чем искать в шаблоне.

Кто подскажет, где они в админ панели. Что-то не нашёл.

13:38
05 сен
#
написал:

Показано на следующем скриншоте (кликните для увеличения).

Как изменить размер списка хитов продаж и акционных товаров

Написание ответа

Перед публикацией рекомендуется использовать Предпросмотр, чтобы увидеть конечный вид сообщения.


Обратите внимание! Для противодействия спаму новые посты форума проявляются с задержкой от нескольких минут, пока не пройдут модерацию.