FENOM'енальный курс. Часть 7. Выводим сгруппированные характеристики товара и реализуем отзывы о товаре.

Шаблон MAGAZINE вы можете скачать по ссылке.

Сейчас мы с вами реализуем один из интересных функционалов для нашего интернет-магазина, а именно вывод сгруппированных характеристик товара. К сожалению, автор miniShop2 не предусмотрел такую возможность из коробки. Но мы же с вами не лыком шиты, верно?

Реализовывать вывод сгруппированных характеристик мы будем на основе сниппета msProductOption, который идет в комплекте с miniShop2. Приведу сразу код модернизированного сниппета getcharacters:

<?php
$product = !empty($product) && $product != $modx->resource->id
    ? $modx->getObject('msProduct', array('id' => $product))
    : $modx->resource;
if (!($product instanceof msProduct)) {
    return "[msProductOptions] The resource with id = {$product->id} is not instance of msProduct.";
}

if ($data = $product->getOne('Data')) {
    $optionKeys = $data->getOptionKeys();
}
if (empty($optionKeys)) {
    return '';
}
$productData = $product->loadOptions();

$options = array();
$catoptions = array();
foreach ($optionKeys as $key) {
    // Filter by key
    if (!empty($onlyOptions) && $onlyOptions[0] != '' && !in_array($key, $onlyOptions)) {
        continue;
    } elseif (in_array($key, $ignoreOptions)) {
        continue;
    }
    $option = array();
    foreach ($productData as $dataKey => $dataValue) {
        $dataKey = explode('.', $dataKey);
        if ($dataKey[0] == $key && (count($dataKey) > 1)) {
            $option[$dataKey[1]] = $dataValue;
        }
    }
    $option['value'] = $product->get($key);

    // Filter by groups
    $skip = !empty($groups) && !in_array($option['category'], $groups) && !in_array($option['category_name'], $groups);
    if ($skip || empty($option['value'])) {
        continue;
    }
    $options[$key] = $option;
    if($option["type"] == 'combo-boolean'){
        if($option['value'][0] == 1 || $option['value'][0] == "Да"){
            $option['value'][0] = "Да";
        }else{
            $option['value'][0] = "Нет";
        }
    }
    if(strlen($option['value'][0])){
        $catoptions[$option['category']]['name'] = $option['category_name'];
        $catoptions[$option['category']]['items'][] = $option; 
    }
}
if($tpl){
    $pdoTools = $modx->getService('pdoTools');
    return $pdoTools->getChunk($tpl, array(
        'cats' => $catoptions,
    ));
}else{
    echo "<pre>";
    print_r($catoptions);
    echo "</pre>";
}
	

Надеюсь, вы заметили, что модернизация коснулась только конца сниппета, следовательно, принимает он все те же параметры, что и msProductOption. Код сниппета нужно сохранить в файле core/elements/snippets/getcharacters.php. Все логику модернизации я подробно расскажу в видео к этому уроку. А мы с вами тем временем должны создать чанк cat_option.tpl:

{foreach $cats as $cat}
    <h4 class="table-title">{$cat.name}</h4>
    <table class="table table-bordered table-middle table-dark">
        <tbody>
            {foreach $cat.items as $option}
            <tr data-key="{$option.key}" data-value="{$option.value[0]}">
                <td style="width: 70%;">
                    {$option.caption}
                </td>
                <td style="width: 30%; text-align: center;">
					{if $option_type == "combo-options"?}
						{var $values = $value | split}
						{foreach $values as $val}
							<span class="label label-default">{$val}</span>
						{/foreach}
						{$option_measure_unit}
					{else}
					  {if $option.value is array}
						  {$option.value | join : ', '}
					  {else}
						  {$option.value}
					  {/if}
					  {if $option.measure_unit?}
						  {$option.measure_unit}
					  {/if}
					{/if}
                </td>
            </tr>
            {/foreach}
        </tbody>
    </table>
{/foreach}
	

На данном чанке у вас должна нарисоваться полная картина всех преимуществ Fenom и логики его работы. Я сам лично сделал ни один подобный функционал. Согласитесь, что все довольно гибко, главное знать всю логику работы. А нам с вами осталось вызвать сниппет в шаблоне карточки товара, для вывода наших характеристик:

{'@FILE snippets/getcharacters.php' | snippet : [
	'tpl' => '@FILE chunks/cat_option.tpl'
 ]}
	

Сейчас мы реализуем отзывы о товаре. Данный блок мы уже разбирали в уроке “Отзывы о товаре в MODx Revo” и здесь у нас принцип не изменится. Мы также будем использовать компонент EasyComm из modStore.pro. Для реализации отзывов о товаре просто перепишем вызовы сниппетов на Fenom синтаксис. И тогда у нас часть шаблона с вкладками примет следующий вид:

<div class="product-tabs">
	<ul class="nav nav-tabs responsive" id="myTab" role="tablist">
		<li class="nav-item">
			<a class="nav-link active" id="characters-tab" data-toggle="tab" href="#characters" role="tab" aria-controls="characters" aria-selected="true">Характеристики</a>
		</li>
		<li class="nav-item">
			<a class="nav-link" id="delievery-tab" data-toggle="tab" href="#delievery" role="tab" aria-controls="delievery" aria-selected="false">Доставка и оплата</a>
		</li>
		<li class="nav-item">
			<a class="nav-link" id="reviews-tab" data-toggle="tab" href="#reviews" role="tab" aria-controls="reviews" aria-selected="false">Отзывы</a>
		</li>
	</ul>
	<div class="tab-content" id="myTabContent">
		<div class="tab-pane fade show active" id="characters" role="tabpanel" aria-labelledby="characters-tab">
			{'@FILE snippets/getcharacters.php' | snippet : [
				'tpl' => '@FILE chunks/cat_option.tpl'
			]}
		</div>
		<div class="tab-pane fade" id="delievery" role="tabpanel" aria-labelledby="delievery-tab">
			{$_modx->getPlaceholder('+delieveryinfo')}
		</div>
		<div class="tab-pane fade" id="reviews" role="tabpanel" aria-labelledby="reviews-tab">
			<div class="customer-review">
				{$_modx->runSnippet('!ecMessages', [])}
			 </div>
			 <div class="leave-review">
				{$_modx->runSnippet('!ecForm', [])}
			 </div>
		</div>
	</div>
</div>
	

Заметили, что мы еще вывели информацию о доставке и оплате из конфигурации ClientConfig? Думаю, что вы сами сможете создать данный параметр и заполнить его тестовой информацией. А как это сделать я покажу в видео.

БОНУС! Хотите, чтобы сниппет в поиске у вас выглядел примерно так:

FENOM&#39;енальный курс. Часть 7. Выводим сгруппированные характеристики товара и реализуем отзывы о товаре.

Мы с вами реализовали блок с отзывами, поэтому сможем сделать аналогичную штуку. Просто добавьте вот этот блок после блока с ценой в шаблоне товара:

		<div class="hidden" itemprop="aggregateRating" itemscope itemtype="http://schema.org/AggregateRating">
			<span itemprop="ratingValue">{$_modx->runSnippet('!ecThreadRating', ['tpl' => 'ratingTpl'])}</span> звезд -
			основано на <span itemprop="reviewCount">{var $output = '!ecMessagesCount' | snippet: ['tpl' => 'ratingTpl'])} {$output ?: '1'}</span> отзывах
		 </div>
	

Данный блок с микроразметкой, позволит вам получить звездочки в Google.

FENOM'енальный курс. Часть 7. Выводим сгруппированные характеристики товара и реализуем отзывы о товаре.

0 Число голосов: 9
4
5
1
9

Комментарии ()

  1. Алексей 23 июля 2019, 06:31 # 0
    Здравствуйте Артем! Скажите пожалуйста как записать данное выражение на феном — это для того чтоб рейтинг вывести в категорию товара

     &loadModels=`easycomm`
    &where=`{"class_key":"msProduct"}`
    &leftJoin=`{
    	"ecThread": {
    		"class": "ecThread",
    		"on": "msProduct.id = ecThread.resource"
    	}
    }`
    
    &select=`{
    	"msProduct": "*",
    	"ecThread": "ecThread.rating_simple AS rating, ecThread.count AS reviews"
    }`
                           	
    1. Алексей 23 июля 2019, 11:03 # 0
      'loadModels'=>'easycomm',
      'where' => ['class_key' => 'msProduct'],
      'leftJoin' => ["ecThread" => [
                                  "class" => "ecThread",
                                  "on" => ["msProduct.id = ecThread.resource"]
                                  ]
                              ],
      'select' => ['msProduct' => '*', 'ecThread' => 'ecThread.rating_simple AS rating, ecThread.count AS reviews'],
      ])} 
    2. Комментарий был удален.
      1. alex minot 10 февраля 2020, 08:24(Комментарий был изменён) # 0
        #######
        1. alex minot 10 февраля 2020, 08:25 # 0
          Приветствую, не знаете можно ли управлять кэшированием файловых сниппетов? (! не работает с вызовами через @FILE)
          1. Руслан 18 января 2021, 21:54(Комментарий был изменён) # 0
            А можно как нибудь присвоить каждой характеристике иконку свою и вывести её на страницу?
            1. Дмитрий 28 июля 2021, 18:38 # 0
              Артём привет. Большое спасибо за уроки! А как сделать выборку для таблицы из двух массивов ПЕРВАЯ КОЛОНКА и ВТОРАЯ КОЛОНКА, у меня всe td идут подряд, как сделать чтобы они чередовались? Спасибо.
              [2] => Array
                                      (
                                          [id] => 10
                                          [key] => product_table_col_01
                                          [caption] => Первая колонка таблицы
                                          [description] => Первая колонка таблицы
                                          [measure_unit] => 
                                          [category] => 15
                                          [type] => combo-options
                                          [properties] => 
                                          [product_id] => 154
                                          [value] => Array
                                              (
                                                  [0] => 123
                                                  [1] => 321
                                                  [2] => 656
                                                  [3] => 565
                                                  [4] => 1233445
                                              )
              
                                          [category_name] => полное описание товара
                                      )
              
                                  [3] => Array
                                      (
                                          [id] => 11
                                          [key] => product_table_col_02
                                          [caption] => Вторая колонка таблицы
                                          [description] => Вторая колонка таблицы
                                          [measure_unit] => 
                                          [category] => 15
                                          [type] => combo-options
                                          [properties] => 
                                          [product_id] => 154
                                          [value] => Array
                                              (
                                                  [0] => бла бла бла
                                                  [1] => бл
                                                  [2] => бла бла
                                                  [3] => и ещё
                                                  [4] => asf qwe r
                                              )
              
                                          [category_name] => полное описание товара
                                      )
              1. Андрей 29 августа 2024, 22:44 # 0
                Артём, здравствуйте! Отличная статья, спасибо! А как сделать, чтобы учитывалась вложенность категорий, например, у меня сейчас есть главная категория «Производительность» и ее дочки «охлаждение» и «обогрев». На фронте у меня должен быть сверху заголовок главной категории «Производительность» и ниже разделение по горизонтали — охлаждение и справа опции по охлаждению и точно так же по обогреву, конечно.

                Наши клиенты

                Многие компании уже доверяют нам. Будьте в их числе!

                Хотите реализовать проект?

                Контакты

                Напишите нам - мы расскажем вам много интересного!


                Пермь, шоссе Космонавтов 252, офис 218