Универсальный виджет get_products

Как и все виджеты в SimplaCMS мы добавим наш в файл view/View.php. После кода (~100 строка)

$this->design->smarty->registerPlugin("function", "get_discounted_products", array($this, 'get_discounted_products_plugin'));

добавим вызов нашего нового виджета

$this->design->smarty->registerPlugin("function", "get_products", array($this, 'get_products_plugin'));

Теперь проще всего скопировать и модифицировать метод get_discounted_products_plugin, но я приведу уже готовый код - в конец файл перед закрывающей } добавим наш говый метод, который мы вызвали выше

	public function get_products_plugin($params, &$smarty)
	{
		if(!isset($params['visible']))
			$params['visible'] = 1;
		if(!empty($params['var']))
		{
			foreach($this->products->get_products($params) as $p)
				$products[$p->id] = $p;

			if(!empty($products))
			{
				// id выбраных товаров
				$products_ids = array_keys($products);
		
				// Выбираем варианты товаров
				$variants = $this->variants->get_variants(array('product_id'=>$products_ids, 'in_stock'=>true));
				
				// Для каждого варианта
				foreach($variants as &$variant)
				{
					// добавляем вариант в соответствующий товар
					$products[$variant->product_id]->variants[] = $variant;
				}
				
				// Выбираем изображения товаров
				$images = $this->products->get_images(array('product_id'=>$products_ids));
				foreach($images as $image)
					$products[$image->product_id]->images[] = $image;
	
				foreach($products as &$product)
				{
					if(isset($product->variants[0]))
						$product->variant = $product->variants[0];
					if(isset($product->images[0]))
						$product->image = $product->images[0];
				}				
			}

			$smarty->assign($params['var'], $products);
			
		}
	}

Поскольку мы делаем плагин для клиентской части, то оставим $params['visible'], чтобы не выводились скрытые товары. С задачей закончили :) В любом файле шаблона теперь можем вызвать наш виджет по аналогии с тем, как выбираются новинки, например

{get_products var=all_products limit=3}
{if $all_products}
{foreach $all_products as $p}
//выводим товар в цикле
{/foreach}
{/if}

В приведенном виде в массиве $all_products будет выбрано 3 первых товара, отсортированных по-умолчанию. Но поскольку это не очень интерено, то привожу список какие наборы товаров мы может получить, причем в различных комбинация. Итак, параметры и их значения

  • limit с числовым значение указывает какое количество товара долно быть в выборке
  • discounted - передав данный параметр со значение 1 мы получим товары со скидкой
  • featured со значение 1 вернет рекомендуемые товары
  • sort может принимать 4 значения - name, created, position и price - вернет товары в той сортировке, которую указали
  • in_stock со значением 1 указывает, что надо только те товары, которые есть в наличии
  • brand_id с числовым индексом бренда вернет товары указанного бренда
  • category_id с числовым индексом категории вернет товары указанной категории
  • keyword со значение к примеру "Samsung" вернет товары где в названии или META встречается указанное слово (поиск по названию)

Первый limit можно сказать основной параметр, т.к. ограничивает нашу выборку.

Последующие 3 - это общий случай стандартных виждетов get_discounted_products, get_featured_products и get_new_products соответственно.

brand_id и category_id в-принципе то, ради чего все и затевалось.

Теперь приведу несколько примеров использования плагина.

Задача 1: вывести максимум 5 новинки того же бренда, что и указанный в карточке товара

{get_products var=brand_products brand_id=$product->brand_id sort='created' limit=5}
{if $brand_products}
{foreach $brand_products as $p}
//выводим товар в цикле
{/foreach}
{/if}

Поскольку в SimplaCMS данные товара указаны в объекте $product, то мы и передаем его значение в наш виджет.

Задача 1.2: вывести 4 товара той же категории, что и указанной в карточке товара

{get_products var=cat_products category_id=category->id limit=5}
{if $cat_products}
{foreach $cat_products as $p}
//выводим товар в цикле
{/foreach}
{/if}

Поскольку в SimplaCMS данные товара указаны в объекте $product, то мы и передаем его значение в наш виджет.

Задача 2: вывести 3 товара со скидкой, которые есть в наличии

{get_products var=cat_products category_id=$category->id discounted=1 in_stock=1 limit=3}
{if $cat_products}
{foreach $cat_products as $p}
//выводим товар в цикле
{/foreach}
{/if}

Задача 3: вывести на главной по 4 рекомендуемых товара каждой "верхней" категории

{foreach $categories as $c}
{if $c->visible}{get_products var=cat_products category_id=$c->id featured=1 limit=4}
{if $cat_products}
<h3>{$c->name}</h3>
{foreach $cat_products as $p}
//выводим товар в цикле
{/foreach}{*foreach $cat_products as $p*}
{/if}{*if $cat_products*}
{/if}{*if $c->visible*}
{/foreach}{*foreach $categories as $c*}

Вот и все на сегодня. Удачи в работе с SimplaCMS!

Комментарии
Дмитрий
хороший виджет. Легко устанавливается. Только в задаче 1.2 ошибка: чтобы вывести товары из той же категории, что указана в карточке товара нужно в get_products указать category_id=$category->id
Все верно. Спасибо, что помогли исправить ошибку.
Андрей
Добрый день!
Вывел в product.tpl, выводится 3 раза тот товар, на странице которого мы находимся. Подскажите в чем может быть проблема?
Выводил так:

<!-- Виджет get_products -->
{get_products var=all_products limit=3}
{if $all_products}
{foreach $all_products as $p}
<!-- Товар-->
<div class="product">
<!-- Фото товара -->
{if $product->image}
<div class="image">
<a href="{$product->url_full}.html"><img src="{$product->image->filename|resize:200:200}"
alt="{$product->name|escape}"/></a>
</div>
{else}
<div class="image">
<a title="{$product->name}" href="{$product->url_full}.html"><img
src="design/{$settings->theme|escape}/images/no_image.jpg"
alt="{$product->name|escape}"/></a>
</div>
{/if}
<!-- Фото товара (The End) -->
<!-- Название товара -->
<a data-product="{$product->id}" href="{$product->url_full}.html">{$product->name|escape}</a>
<!-- Название товара (The End) -->
<!-- Стоимость товара -->
<div class="pricemain">
{if $product->variant->compare_price > 0}
<span class="akcia">{$product->variant->compare_price|convert} {$currency->sign|escape}</span>
<br>
{/if}
<span>{$product->variant->price|convert} {$currency->sign|escape}</span>
</div>
<!-- Стоимость товара конец -->
</div>
<!-- Товар (The End)-->
{/foreach}
{/if}
<!-- Виджет get_products /-->
Добрый день У Вас ошибка в коде Внутри foreach вы используете переменную $product а нужно $p
Стас
Добрый день, виджет отличный, работает в шаблоне рубрики.
Но никак не могу его заставить работать в шаблоне товара. У каждого товара много вариантов, и нужно выводить названия только первых 5 вариантов товара.

Добрый день, 
вы можете заказать у нас данную доработку,
(так как данная доработка в описание бесплатной статьи не входит)
По стоимости 1200 руб. 

yaskin
в задаче 1.2 ошибка или описка в первой строке
правильно писать не brand_id а category_id

Добрый день, да действительно, была допущена опечатка в коде.
Спасибо, вам большое за ваш комментарий и возможность усовершенствовать наш сайт.
Мы внесли измения в код, теперь все прописано правильно. 

АЛександр
а можно вывести товары по запросу для поиска?

можно. нужно добавить в вызов виджета keyword="Мой запрос", т.е. {get_products var=some_products keyword="Мой запрос"}

Владимир
Здравствуйте! Спасибо за отличный виджет! Но как вывести случайные товары из той же категории, и того же бренда! Благодарю!

Доброе время суток!

Изначально нету возможности случайной сортировки товаров, поэтому необходимо добавить в файлу /api/Products.php в методе get_products после:

case 'created':
$order = 'p.created DESC';
break;

вставить:

case 'rand':
$order = ' RAND() ';

После этого у вас будет возможность случайной сортировки товаров.

Тогда для вывода товаров Вам необходимо взять значения идентификатора бренда и категории у товара и передать данные в виджет.

Вася
Выводим товары со скидкой в открытой категории.
{get_products var=cat_products category_id=$category->id discounted=1 in_stock=1 limit=12}
{if $cat_products}
{foreach $cat_products as $p}
........
{/foreach}
{/if}

Здравствуйте!
Подскажите как правильно сделать все то что указано выше, только с учетом выбранного бренда в фильтре.
если я вставляю brand_id=$product->brand_id в первую строку, то все рботает, но когда в фильтре выбран пункт "все бренды" который стоит по умолчанию, то все равно показывает только 1 из брендов.
Подскажите как более верно задать условие, чтобы когда стоит все бренды, выводились товары по всем брендам данной категории, а когда выбран конкретный бренд то товары этого бренда со скидкой из данной категории.
Благодарю!

Это условие
brand_id=$product->brand_id
в корне не верно. Для того, чтобы выбрать товары интересующего вас бренда нужно знать id этого бренда(это можно посмотреть в админке) или находится на странице с выбранным брендом.

Касательно странички категории  с выбранным брендом и просто странички категории верным будет следующее условие
{if $brand}
        {get_products var=cat_products category_id=$category->id brand_id=$brand->id discounted=1 in_stock=1 limit=12}
{else}
        {get_products var=cat_products category_id=$category->id discounted=1 in_stock=1 limit=12}
{/if}

{if $cat_products}
{foreach $cat_products as $p}
........
{/foreach}
{/if}

В таком случае если бренд выбран, то товары со скидкой выберутся с учетом выбранного бренда, в противном случае выберутся товары из текущей категории

Максим
Как сделать проверку на текущий товар, дабы он в этом цикле не выводился?

{get_products var=brand_products brand_id=$product->brand_id sort='created' limit=5}
{if $brand_products}
{foreach $brand_products as $p}
//выводим товар в цикле
{/foreach}
{/if}

{get_products var=brand_products brand_id=$product->brand_id sort='created' limit=5}
{if $brand_products}
{foreach $brand_products as $p}
{if $p->id != $product->id}
//выводим товар в цикле
{/if}
{/foreach}
{/if}

Макс
А как вызвать на главной товары из категории которых нет в наличии? И Спасибо за плагин!