modRelation - Похожие товары для minishop2 и pdoTools


В общем кратенькая заметка, но думаю некоторым поможет, нужно было реализовать правильную перелинковку сайта, а заказчик никак не хотел вручную делать связи, пришлось написать вот такой «Умный» сниппет, который при правильном заполнении каталога вполне неплохо себе справляется с подбором похожих ресурсов, если я ни для кого америку не открыл, то сорян, а если открыл, то могу собрать пакет с этим сниппетом и выложить в modstore бесплатно для более легкой установки :)

ОБНОВЛЕНО:
Компонент доступен для загрузки в modstore

Описание работы:
Сниппет разделяет по словам поле, которое вы укажите в field (по умолчанию pagetitle), выбирает рандомное слово из массива слов и выполянет поиск по базе ресурсов с похожими словами

Сниппет:
<?php
if (empty($field)) {
  $field = 'pagetitle';
}
if (empty($separator)) {
  $separator = ' ';
}
if (empty($element)) {
  $element = 'pdoResources';
}
if (empty($limitWord)) {
  $limitWord = 3;
} else {
  $limitWord = intval($limitWord);
}
$pagetitle = $modx->resource->get($field);
if (!$pagetitle) {
  return ;
}
$arr = explode($separator, $pagetitle);
$rand = array_rand($arr, 1);
while (iconv_strlen($arr[$rand]) < $limitWord):
  $rand = array_rand($arr, 1);
endwhile;

$rand_pt = $arr[$rand];

$where = array('where' => array(
    $field.':LIKE' => '%'.$rand_pt.'%',
    'id:!=' => $modx->resource->id
));

$scriptProperties = array_merge($where, $scriptProperties);
$pdoTools = $modx->getService('pdoTools');
return $pdoTools->runSnippet($element, $scriptProperties);
Внимание, код устаревший, используйте версию из modstore

Принимает на вход:
  • field — поле по которому будут искаться похожие ресурсы, можно использовать любые поля ресурса, если это не тв параметры по умолчанию pagetitle
  • separator — разделитель по которому будет делиться объекты для поиска по умолчанию пробел
  • limitWord — минимальная длина слова для поиска похожих ресурсов, по умолчанию 3
  • element — сниппет для вывода результатов, по умолчанию pdoResource
Далее просто передаете парметры нужные для сниппета elements, принцип работы по типу pdoPage

Примеры вызова:

Простой вызов для msProducts
[[!modRelation? 
  &element=`msProducts`
  &parents=`0`
  &sortby=`RAND()`
]]
Со всеми параметрами:
[[!modRelation? 
  &field=`pagetitle`
  &separator=` `
  &limitWord=`3`
  &element=`msProducts`
  &parents=`0`
  &tpl=`tpl_product_row`
  &sortby=`RAND()`
]]
Пример использования для статей и обычных ресурсов:
[[!modRelation? 
  &parents=`0`
  &sortby=`RAND()`
  &tpl=`@INLINE [[+pagetitle]]`
]]
Сниппет работает как с продуктами minishop2 так и с обычными ресурсами
07 ноября 2017, 09:51    Pavel Zarubin   G+  
14    1171 +13


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

  1. Yar 07 ноября 2017, 10:08 # 0
    Сегодня же воткну на сайт, спасибо
    1. Василий Столейков 07 ноября 2017, 10:12 # 0
      Интересное решение!
      Раньше пользовался для этих целей getRelated, твоё решение мне больше нравится простотой и интеграцией с pdoTools!
      Можно и в пакет запаковать ))
      1. Максим Кузнецов 07 ноября 2017, 12:29 # +6
        На fenom-е посимпатичнее будет:

        {foreach $_modx->resource.pagetitle | split : ' ' as $pagetitle_word}
        	{if $pagetitle_word | length > 3}
        		{var $words[] = $pagetitle_word}
        	{/if}
        {/foreach}
        
        {set $random_word_position = rand(1, $words| length)}
        {set $random_word = $words[$random_word_position - 1]}
        
        {$_modx->runSnippet('!msProducts', [
        	'parent' => $_modx->resource.parent,
        	'resources' => -$_modx->resource.id,
        	'where' => '{
        		"pagetitle:LIKE": "%' ~ $random_word ~ '%"
        	}',
        	...
        ])}
        1. Pavel Zarubin 07 ноября 2017, 13:29 # +1
          Вкусовщина конечно, но не хотел бы я чтобы мне попался проект где вот таких вот сниппетов в шаблоне с десяток) Все таки надо разделять верстку и программирование, вы же не пишите все операции в одном файле, а резделяете на функции/классы, хоть их вызов и отнимает больше времени, но лайк однозначно поставлю!)
          1. Максим Кузнецов 07 ноября 2017, 13:37 # 0
            *пожал плечами* Для больших объемов или многократно повторяющихся вызовов — пожалуй.

            В данном случае «похожие товары», скорее всего, будут выводиться только на странице самого товара.
            Плюс, с fenom-ом кол-во запросов к бд сокращается минимум на 1..)

            К слову, по поводу разделения: логику разбивания и выборки случайного слова из заголовка можно вынести в модификатор.
        2. Pavel Zarubin 07 ноября 2017, 14:38 # +1
          Обновление: Раз сниппет оказался много кому нужен, собрал транспортный пакет и допилил его вид до более универсального
          1. Pavel Zarubin 07 ноября 2017, 14:55 # +1
            Как только опубликуют в modstore допилю похожесть по полям цвета и размера, эти поля хранят не строку, а массив
          2. carlo 07 ноября 2017, 23:06 # +2
            Can I use this plugin like GetRelated for Modx? Does it work with Articles?

            I am so sorry, I don't speak Russian.

            Google Translate:

            Могу ли я использовать этот плагин, как GetRelated для Modx? Это работает со статьями?

            Мне очень жаль, я не говорю по-русски.
            1. Pavel Zarubin 08 ноября 2017, 08:19 # +4
              Sure, simple example for use:
              [[!modRelation? 
                &parents=`0`
                &element=`pdoResources`
                &tpl=`@INLINE [[+pagetitle]] 
              `
              ]]
              
              1. carlo 08 ноября 2017, 17:19 # +1
                Thank you! I will try that!
                1. carlo 11 июня 2018, 22:25 # 0
                  Hi Pavel, I am trying to implement your code

                  [[!modRelation? 
                    &parents=`3,157,158,159`
                    &limit=`3`
                    &element=`pdoResources`
                    &includeTVs=`featureimage`
                    &tpl=`modrelationchunck`
                    &wrapIfEmpty=`modrelationchunck`
                  ]]
                  
                  Do you think is it possible to display a default chunck or result if result is empty?
                  1. carlo 12 июня 2018, 16:43 # 0
                    It is ok, I managed to do it with
                    [[!modRelation:default=``?
                    .

                    I just have 2 questions:

                    — What can I use for &field?
                    — is it necessary to call the plugin uncached?
              2. Олег 14 ноября 2017, 10:40 # 0
                А как быть с опциями товаров?
                Мне надо чтобы похожие шины выводил по ширине, высоте и радиусу.
                1. Pavel Zarubin 14 ноября 2017, 11:03 # +1
                  Пока что нет такого функционала, нет времени и желания (да и желающих на него тоже нет), возможно вы хотите проспонсировать разработку, тогда добро пожаловать в личные сообщения :)
                2. Yar 15 ноября 2017, 14:36 # 0
                  c Tickets не работает чтоли? При вызове снипета — выводится пустая страница
                  1. Pavel Zarubin 15 ноября 2017, 14:38 # 0
                    Покажи вызов сниппета
                    1. Yar 15 ноября 2017, 14:40 # 0
                      [[!modRelation? 
                        &parents=`0`
                        &sortby=`RAND()`
                        &includeTVs=`image`
                        &tpl=`tpl-side-bar-articles`
                        &element=`getTickets`
                      ]]
                      1. Pavel Zarubin 15 ноября 2017, 14:51 # 0
                        Только что проверил скопировав твой вызов все нормально отрабатывает, если можешь прислать доступы в личку, пришли гляну
                      2. Yar 15 ноября 2017, 14:42 # 0
                        с
                        &element=`pdoResources`
                        тоже самое — пустая страница. Вызов на странице тикета
                    2. v2254303 15 декабря 2017, 21:19 # 0
                      А как сделать чтобы не выводились записи рандомно при каждом обновлении страницы

                      <div class="modrelation">
                            <div class="modrelation_title">Похожие темы</div>  
                      {$_modx->runSnippet('!modRelation',[
                      			'field' => 'pagetitle',
                      			'parents' => '0',
                      			'element' => 'msProducts',
                      			'tpl' => '@FILE chunks/products/item-catalog.tpl',
                      ])}
                      </div>
                      1. Pavel Zarubin 15 декабря 2017, 22:02 # 0
                        Сделай сниппет некешируемый, убрав восклицательный знак в вызове, тогда результаты будут сгенерированы только один раз
                      2. Андрей 22 марта 2018, 09:23 # 0
                        Подскажите, вывожу сниппет, наглухо вешает страницу. В результате 504 ошибка. Что может быть?
                        {'!modRelation' | snippet : [
                                            'element' => 'msProducts',
                                            'parents' => 2,
                                            'sortby' => 'RAND()',
                                            'limit' => 3,
                                        ]}
                        1. Александр 10 апреля 2018, 13:12 # 0
                          Такая же проблема. Удалось решить?
                        2. Alex Zhuravlev 26 марта 2018, 00:53 # 0
                          А как в field указать свое кастомное поле из minishop?

                          У меня в товаре есть кастомное поле где я прописываю параметры товара и нужно выводить похожие по этому полю, указываю его в field но ничего не выводит.
                          1. Владимир 14 июня 2018, 17:26 # 0
                            Почему-то дополнение modRelation не найдено в магазине приложений.
                            Вы должны авторизоваться, чтобы оставлять комментарии.