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

Следить
Главная
15:48
07 ноя
#
?
написал:
  • Категория 1 (информативная)
    • Категория 1.2
  • Категория 2 (информативная)
    • Категория 2.1 (информативная)
      • Категория 2.1.1
      • Категория 2.1.2
      • Категория 2.1.3
    • Категория 2.2
    • Категория 2.3

Помогите правильно реализовать вывод ТОП 10 (просматриваемых) товаров на странице категории, при включенном флажке "информативная".

Суть вопроса такова: На сайте есть множество категорий с несколькими уровнями подкатегорий. Все страницы, которые содержат подкатегории сделаны "информативными". На них выводится список подкатегорий в виде каталога + небольшое описание и иногда SEO-текст.

Хотелось бы под каталогом вывести блок "Популярные товары в категории "Наименование_текущей_категории"", и в нем показать Топ10 товаров по просмотрам. Но как сделать так, чтобы учитывались все товары из вложенных категорий (например как на схеме для категории 2)?

21:12
07 ноя
#
?
написал:

Кажется без php здесь не обойтись. Селектить топ10 товары.
Специальных опций в бекенде не вижу на этот случай.

Наверно всё ж руками залезть в код двигла и дописать селект.
При апгрейде всё слетит и заново дописывать.

А что разработчик скажет; php в шаблоне не работает?
У меня другая задача надо на главной показать 5 новых отзывов.

09:25
08 ноя
#
написал:

Еще в мартовском релизе 2012 года появилась поддержка эмулятора (собственных php-обработчиков, smarty-модификаторов, smarty-плагинов) файлов шаблона. С его помощью в отдельно взятый шаблон можно встроить программную php-логику в принципе какой-угодно сложности, и она не будет затираться при обновлениях движка, так как логика относится только к этому шаблону и размещена вне области обновляемых файлов.

Если в папку шаблона поместить файл http://ваш.сайт/design/ваш-шаблон/html/emulator.php, где для нужных вам tpl-файлов шаблона согласно вашей задаче прописать недостающие установки переменных или запросы к базе данных, вы получите желаемый результат.

Сначала приведу общий каркас файла эмулятора, и следом пример решения задачи Руслана и задачи Григория.

<?php
    // =======================================================================
    /**                                                                       
    *  Эмулятор шаблона клиентской стороны сайта                              
    *                                                                         
    *  -----------------------------------------------------------------------
    *                                                                         
    *  Если в шаблоне требуются какие-то специфичные php-обработки, тогда     
    *  эмулятор помещается в виде файла emulator.php в папку шаблона, а именно
    *  http://ваш.сайт/design/ваш-шаблон/html/emulator.php, в результате      
    *  система шаблонизации конкретно для данного шаблона начинает работать   
    *  под управлением эмулятора. Остальные шаблоны, в которых такой файл     
    *  эмулятора не существует, обрабатываются стандартным образом.           
    *                                                                         
    *  Подробности читайте ниже в описании метода prepare. Также обратите     
    *  внимание на описание метода setSmartyPlugins.                          
    *                                                                         
    *  -----------------------------------------------------------------------
    *                                                                         
    *  @package     Impera CMS                                                
    *  @author      AIMatrix                                                  
    *  @copyright   Copyright 2012, AIMatrix                                  
    *  @link        http://imperacms.com                                       
    */                                                                        
    // =======================================================================

    class TemplateEmulator {



        // объект движка
        public $cms = null;



        // ===================================================================
        /**                                                                   
        *  Конструктор класса                                                 
        *                                                                     
        *  -------------------------------------------------------------------
        *                                                                     
        *  @access  public                                                    
        *  @param   object  $cms        объект движка                         
        *  @return  void                                                      
        */                                                                    
        // ===================================================================

        public function __construct ( & $cms ) {

            // запоминаем выход на объект движка
            $this->cms = & $cms;

            // подключаем наши функции и модификаторы Smarty
            $this->setSmartyPlugins($cms);
        }



        // ===================================================================
        /**                                                                   
        *  Подключение наших функций и модификаторов в шаблонизатор Smarty    
        *                                                                     
        *  -------------------------------------------------------------------
        *                                                                     
        *  Здесь выполняем регистрацию наших собственных Smarty-плагинов и    
        *  модификаторов, которые станут доступны во всех файлах шаблона.     
        *                                                                     
        *  Например, если хотим, чтобы в шаблоне можно было использовать      
        *  такой модификатор, скажем my_date, который в файле шаблона         
        *  записывался бы следом за модифицируемой переменной как             
        *                                                                     
        *      {$date = '12 March 2012'}                                      
        *      {$date|my_date:'d.m.Y'}                                        
        *                                                                     
        *  то регистрацию этого модификатора нужно было прописать в данном    
        *  методе в виде строк                                                
        *                                                                     
        *      $cms->smarty->registerPlugin('modifier',                       
        *                                   'my_date',                        
        *                                   array($this, 'my_date_handler')); 
        *                                                                     
        *  а также добавить метод my_date_handler, где закодировать сам       
        *  обработчик модификатора, например                                  
        *                                                                     
        *      public function my_date_handler ( $value, $format = '' ) {     
        *          if ($format == '') $format = 'd.m.Y';                      
        *          $value = strtotime($value);                                
        *          if ($value === -1) return 'Неверная дата!';                
        *          return date($format, $value);                              
        *      }                                                              
        *                                                                     
        *  Аналогично прописывается регистрация плагинов (функций), скажем    
        *  мы хотели бы использовать в шаблоне некую функцию, допустим        
        *  записываемую так                                                   
        *                                                                     
        *      {set_header code = 404}                                        
        *                                                                     
        *  тогда регистрация этой функции будет выглядеть в виде строк        
        *                                                                     
        *      $cms->smarty->registerPlugin('function',                       
        *                                   'set_header',                     
        *                                 array($this, 'set_header_handler'));
        *                                                                     
        *  а также добавить метод set_header_handler, где закодировать сам    
        *  обработчик функции, например                                       
        *                                                                     
        *      public function set_header_handler ( $params, & $smarty ) {    
        *          if (isset($params['code']) {                               
        *              switch ($params['code']) {                             
        *                  case 404:                                          
        *                      header('HTTP/1.0 404 Not Found');              
        *                      break;                                         
        *              }                                                      
        *          }                                                          
        *          return '';                                                 
        *      }                                                              
        *                                                                     
        *  Модификатор всегда возвращает модифицированное значение исходной   
        *  переменной, функция - что вывести на страницу в том месте, где     
        *  была вызвана функция.                                              
        *                                                                     
        *  -------------------------------------------------------------------
        *                                                                     
        *  @access  protected                                                 
        *  @param   object  $cms        объект движка                         
        *  @return  void                                                      
        */                                                                    
        // ===================================================================

        protected function setSmartyPlugins ( & $cms ) {
        }



        // ===================================================================
        /**                                                                   
        *  Подготовка к отрисовке файла шаблона                               
        *                                                                     
        *  -------------------------------------------------------------------
        *                                                                     
        *  Принцип работы эмулятора: перед отрисовкой каждого файла шаблона   
        *  движок сначала передает управление в этот метод эмулятора, чтобы   
        *  эмулятор либо дополнил список Smarty-переменных какими-то          
        *  недостающими сведениями, либо отрисовал контент по-своему,         
        *  либо отдал право отрисовки назад шаблонизатору.                    
        *                                                                     
        *  Если эмулятор хочет отрисовать контент по-своему, он должен        
        *  сгенерировать этот контент и возвратить во входную переменную $body
        *                                                                     
        *  Если эмулятор хочет отдать право отрисовки назад в шаблонизатор,   
        *  он должен установить входную переменную $body = null, а на выход   
        *  метода возвратить имя файла, который он приказывает отрисовать. Как
        *  правило, имя файла будет равным входному имени ($template->name),  
        *  однако может быть и сменено на другое (например, эмулятор          
        *  динамически подготовил какой-то новый или временный tpl-файл и     
        *  просит отрисовать именно его).                                     
        *                                                                     
        *  Если эмулятор хочет дополнить список Smarty-переменных, он может   
        *  использовать метод $cms->smarty->getTemplateVars('var_name')       
        *  для чтения уже существующей к этому времени Smarty-переменной и    
        *  метод $cms->smarty->assignByRef('new_var_name', $myvar) для        
        *  установки новой переменной. Например хотим на основе содержимого   
        *  переменной title создать другую переменную title2:                 
        *                                                                     
        *      $title = $cms->smarty->getTemplateVars('title');               
        *      $title .= ' купить в Украине';                                 
        *      $cms->smarty->assignByRef('title2', $title);                   
        *                                                                     
        *  Необходимо помнить, что новые назначенные Smarty-переменные будут  
        *  доступны и в других файлах шаблона (в данном случае в файле        
        *  index.tpl, так как он рисуется всегда последним, после отрисовки   
        *  прочих tpl-файлов).                                                
        *                                                                     
        *  -------------------------------------------------------------------
        *                                                                     
        *  @access  public                                                    
        *  @param   object  $template       сведения об имени шаблона:        
        *                                       ->name = имя файла реальное   
        *                                       ->impera_name = имя файла     
        *                                                    (без расширения) 
        *                                                    по Impera CMS    
        *                                       ->standard_name = имя файла   
        *                                                    (без расширения) 
        *                                                    типичное         
        *  @param   object  $cms            объект движка                     
        *  @param   string  $body           null (если отрисовку отдаем       
        *                                         шаблонизатору)              
        *                                   или сгенерированный нами контент  
        *  @return  string                  имя файла шаблона (если отрисовку 
        *                                                отдаем шаблонизатору)
        */                                                                    
        // ===================================================================

        public function prepare ( $template, & $cms, & $body = null ) {

            // мы не хотим генерировать контент сами
            $body = null;



            // какой файл сейчас обрабатывается?
            $name = strtolower($template->name);
            switch ($name) {



                // общий макет страницы (отрисовывается всегда самым последним)
                case 'index.tpl':
                case 'page.tpl':
                    break;



                // страница Каталог (как правило, ее делают главной)
                case 'catalog.tpl':
                case 'page.catalog.tpl':
                    // здесь будет правка по задаче Григория,
                    // так как список недавних отзывов нужно 
                    // показать именно на "главной" странице 
                    break;



                // страница Список товаров
                case 'products.tpl':
                case 'page.products.tpl':
                    // здесь будет правка по задаче Руслана,
                    // так как ТОП10 товаров нужно показать 
                    // именно на странице категории (списке 
                    // ее товаров)                          
                    break;

                // страница Товар
                case 'product.tpl':
                case 'page.product.tpl':
                    break;



                // страница Личный кабинет
                case 'account.tpl':
                    break;



                // страница Список статей
                case 'articles.tpl':
                    break;

                // страница Статья
                case 'article.tpl':
                    break;



                // страница Позвоните мне
                case 'callme.tpl':
                    break;



                // страница Корзина
                case 'cart.tpl':
                    break;

                // всплывающая плашка "Товар добавлен в корзину"
                case 'page.quick_cart.tpl':
                    break;



                // страница Сравнение товаров
                case 'compare.tpl':
                    break;

                // всплывающая плашка "Товар добавлен в сравнение"
                case 'page.quick_compare.tpl':
                    break;



                // страница Обратная связь
                case 'feedback.tpl':
                    break;



                // страница Список медиа файлов
                case 'files.tpl':
                    break;

                // страница Медиа файл
                case 'file.tpl':
                    break;



                // страница Авторизация
                case 'login.tpl':
                    break;

                // страница Забыли пароль?
                case 'password_remind.tpl':
                    break;

                // страница Регистрация
                case 'registration.tpl':
                    break;



                // блок кнопок листания страниц списка
                case 'navigation.htm':
                    break;



                // страница Список новостей
                case 'news.tpl':
                    break;

                // страница Новость
                case 'news_item.tpl':
                    break;



                // страница Уведомить о наличии
                case 'notifyme.tpl':
                    break;



                // страница Оформленный заказ
                case 'order.tpl':
                    break;

                // страница Заказ оформлен успешно
                case 'order_success.tpl':
                    break;



                // страница Конфигуратор
                case 'page.configurator.tpl':
                    break;



                // страница Результаты поиска
                case 'search.tpl':
                    break;



                // страница Карта сайта
                case 'sitemap.tpl':
                    break;



                // страница Специальная страница
                case 'static_page.tpl':
                    break;



                // страница Список складов
                case 'stocks.tpl':
                    break;

                // страница Склад
                case 'stock.tpl':
                    break;



                // информер для внешних сайтов
                case 'informer.tpl':
                    break;



                // скачиваемый прайс-лист
                case 'price.tpl':
                case 'price2.tpl':
                case 'price3.tpl':
                case 'price4.tpl':
                case 'price5.tpl':
                case 'price6.tpl':
                case 'price7.tpl':
                case 'price8.tpl':
                    break;



                // иначе какой-то другой файл
                default:
            }



            // просим шаблонизатор отрисовать этот файл                    
            // (иначе мы должны были бы поместить в $body свою "отрисовку")
            return $template->name;
        }
    }



    return;
?>


Решение для Руслана Как было помечено выше красным цветом, изменению подвергнется соответствующая часть метода prepare, отвечающая за контроль отрисовки страницы списка товаров.

Суть работы следующего кода состоит в том, что мы сначала извлекаем из шаблонизатора состояние переменной $category, где хранится запись о текущей категории. Далее готовим фильтр, учитывая в нем все необходимые нам параметры отбора товаров, в том числе что товары в заданном количестве нужно отобрать только видимые пользователям и непременно из текущей категории (вместе с вложенными ветвями). Причем не забываем учесть в фильтре, что в этот момент страницу может просматривать авторизованный пользователь со своей скидкой и ценовой группой, следовательно цены товаров должны быть автоматически пересчитаны под этого пользователя. Далее выполняем селекцию товаров и передаем результирующий список товаров обратно в шаблонизатор, чтобы они стали доступны в шаблоне через переменную $top10_products.

...
...

// страница Список товаров
case 'products.tpl':
case 'page.products.tpl':

    // извлекаем из шаблонизатора переменную текущей категории
    $category = $cms->smarty->getTemplateVars('category');



    // начинаем настройку фильтра
    $items = null;
    $filter = new stdClass;

    // только просмотренные
    $filter->browsed = 1;

    // именно из этой категории
    $filter->category = & $category;

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

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

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

    // из результата отобрать первые 10 товаров
    $filter->start = 0;
    $filter->maxcount = 10;

    // если это авторизованный посетитель, в ценах товаров учитывать его скидку и ценовую группу
    $filter->discount = isset($cms->user->discount) ? $cms->user->discount : 0;
    $filter->price_id = isset($cms->user->price_id) ? $cms->user->price_id : 0;



    // выполняем выборку из базы данных
    $cms->db->products->get($items, $filter);

    // распаковываем поля записей (некоторые поля хранятся в базе в нестандартном виде)
    $cms->db->products->unpack_records($items, $filter);



    // передаем товары в шаблонизатор
    $cms->smarty->assignByRef('top10_products', $items);
    break;

...
...


Решение для Григория Похоже по сути действия, только отбираем отзывы о товарах. Настраиваем фильтр так, чтобы отобрать требуемое число недавних постов, для чего записи просим отобрать плоским списком (игнорируя ветвистость ответов) и только промодерированные, то есть разрешенные посты. Результирующий список отправляем обратно в шаблонизатор под именем переменной $top5_comments.

...
...

// страница Каталог (как правило, ее делают главной)
case 'catalog.tpl':
case 'page.catalog.tpl':

    // начинаем настройку фильтра
    $items = null;
    $filter = new stdClass;

    // только промодерированные
    $filter->enabled = 1;

    // результат нужен плоским списком (без ветвистости)
    $filter->flatlist = 1;

    // порядок записей хотим перевернуть (то есть от новых к старым)
    $filter->reverse = 1;

    // из результата отобрать первые 5 отзывов
    $filter->start = 0;
    $filter->maxcount = 5;



    // выполняем выборку из базы данных
    $cms->db->get_comments($items, $filter);



    // передаем отзывы в шаблонизатор
    $cms->smarty->assignByRef('top5_comments', $items);
    break;

...
...
16:33
08 ноя
#
?
Michael написал:

Вы ошиблись по задаче Руслана top10 должен на информативных категориях появляться. У вас он читается для любой категории. К тому же можем стоть не в категории а бренде. Следовательно надо ввести проверку.

// страница Список товаров
case 'products.tpl':
case 'page.products.tpl':

    // извлекаем из шаблонизатора переменную текущей категории
    $category = $cms->smarty->getTemplateVars('category');

    // не в категории или она обычная - значит стоп
    if (!isset($category->informative) || !$category->informative) break;

    ...
    ...
17:19
08 ноя
#
?
написал:

Как вы ещё не утонули в этой системе. На каждую хрень стописят способов реализации.
Вот ещё один проще без гимороя с именами шаблона.

<?php
    class TemplateEmulator {
        public $cms = null;

        public function __construct ( & $cms ) {
            $this->cms = & $cms;
            $this->setSmartyPlugins($cms);
        }

        protected function setSmartyPlugins ( & $cms ) {
            $cms->smarty->registerPlugin('function', 'top_products', array($this, 'get_top_products'));
            $cms->smarty->registerPlugin('function', 'last_comments', array($this, 'get_last_comments'));
        }

        public function get_top_products ( $params, & $smarty ) {
            $filter = new stdClass;
            $filter->browsed = 1;
            if (isset($params['cat'])) $filter->category = $params['cat'];
            $filter->enabled = 1;
            if (!isset($this->cms->user->user_id)) $filter->hidden = 0;
            $filter->sort = SORT_PRODUCTS_MODE_BY_BROWSED;
            $filter->sort_direction = SORT_DIRECTION_DESCENDING;
            $filter->start = 0;
            $filter->maxcount = isset($params['count']) ? $params['count'] : 10;
            $filter->discount = isset($this->cms->user->discount) ? $this->cms->user->discount : 0;
            $filter->price_id = isset($this->cms->user->price_id) ? $this->cms->user->price_id : 0;

            $items = null;
            $this->cms->db->products->get($items, $filter);
            $this->cms->db->products->unpack_records($items, $filter);
            return $items;
        }

        public function get_last_comments ( $params, & $smarty ) {
            $filter = new stdClass;
            $filter->enabled = 1;
            $filter->flatlist = 1;
            $filter->reverse = 1;
            $filter->start = 0;
            $filter->maxcount = isset($params['count']) ? $params['count'] : 5;

            $items = null;
            $this->cms->db->get_comments($items, $filter);
            return $items;
        }
    }
?>

Так в любом файле шаблона доступны функции top_products и last_comments.
Примеры вызова

{top_products cat = $category|default:false count = 10 assign = 'result'}
{foreach $result as $product}
    {$product->model|escape} <hr>
{/foreach}
{last_comments count = 5 assign = 'result'}
{foreach $result as $comment}
    {$comment->comment|escape} <hr>
{/foreach}
17:28
08 ноя
#
?
написал:

Ещё пример top 10 товаров из любых категорий

{top_products count = 10 assign = 'result'}
{foreach $result as $product}
    {$product->model|escape} <hr>
{/foreach}
15:40
13 ноя
#
?
написал:

Спасибо, получилось! Использовал вариант Разработчика с правками от Michael.

А как фильтрануть еще по наличию? То есть убрать из списка все отсутствующие товары.

17:43
13 ноя
#
написал:

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

...
...

// страница Список товаров
case 'products.tpl':
case 'page.products.tpl':

    // извлекаем из шаблонизатора переменную текущей категории
    $category = $cms->smarty->getTemplateVars('category');



    // начинаем настройку фильтра
    $items = null;
    $filter = new stdClass;

    // только просмотренные
    $filter->browsed = 1;

    // только без признака "Не для продажи"
    $filter->non_usable = 0;

    // только имеющиеся в наличии от 1 и более штук
    $filter->search_amount_from = 1;

    // только с ненулевой ценой (админ в принципе может и товар с ценой 0 создать)
    $filter->search_cost_from = 0.01;

    // именно из этой категории
    $filter->category = & $category;

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

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

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

    // из результата отобрать первые 10 товаров
    $filter->start = 0;
    $filter->maxcount = 10;

    // если это авторизованный посетитель, в ценах товаров учитывать его скидку и ценовую группу
    $filter->discount = isset($cms->user->discount) ? $cms->user->discount : 0;
    $filter->price_id = isset($cms->user->price_id) ? $cms->user->price_id : 0;



    // выполняем выборку из базы данных
    $cms->db->products->get($items, $filter);

    // распаковываем поля записей (некоторые поля хранятся в базе в нестандартном виде)
    $cms->db->products->unpack_records($items, $filter);



    // передаем товары в шаблонизатор
    $cms->smarty->assignByRef('top10_products', $items);
    break;

...
...

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

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


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