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+  
12    395 +13

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

  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!
            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`
                      тоже самое — пустая страница. Вызов на странице тикета
                  Вы должны авторизоваться, чтобы оставлять комментарии.