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

Имеется база товаров, входящие в различные категории
Необходимо вывести список товаров с категориями (основной и дополнительными)

Всего примерно 50 категорий. У товара назначены от 1 до 3 категорий
Вывод 18 карточек товаров на странице с выводом категорий занимает 12секунд, при отключении сниппета 1с

Помогите привести сниппет в божеский вид или может есть другой вариант вывода?

Код Сниппета mscat.php
<?php
if (empty($limit)) {$limit = 10;}
if (empty($rid)) {$rid = $modx->resource->id;}
if (empty($pid)) {$pid = $modx->resource->parent;}
if (empty($delimeter)) {$delimeter = ' , ';}
$scheme = $modx->getOption('link_tag_scheme', null, 'full', true);

$q = $modx->newQuery('msCategory');
$q->leftJoin('msCategoryMember', 'msCategoryMember', array(
    '`msCategory`.`id` = `msCategoryMember`.`category_id`'
));
$q->sortby('pagetitle','ASC');
$q->groupby('id');
$q->select(array('id','pagetitle'));
$q->where('`msCategoryMember`.`product_id` = '.$rid.' OR `id` = '.$pid);
$count = 1;
$result = array();

if ($q->prepare() && $q->stmt->execute()) {
    while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
    	if ($count <= $limit){
        $url = $modx->makeUrl($row['id'], '', '', $scheme);
        $result[] = '<a href="'.$url.'">'.$row['pagetitle'].'</a>';
        $count++;
    	}
    }
}
return implode($delimeter, $result);
В чанке карточки товара вызываю сниппет:
{$_modx->runSnippet("@FILE snippets/mscat.php", [
				'rid' => $id,
				'pid' => $parent,
				'delimeter' => ' / '
			])}
kgb3000
18 октября 2021, 01:35
modx.pro
670
0

Комментарии: 6

Павел Романов
18 октября 2021, 10:33
0
А если так?
$parent = $modx->getObject('modResource', $pid);
$result[] = '<a href="'.$modx->getOption('site_url').$parent->get('uri').'">'.$parent->get('pagetitle').'</a>';

$table = $modx->getOption('table_prefix').'ms2_product_categories';
$sql = "SELECT * FROM {$table} WHERE `product_id` = {$rid}";
$q = $modx->prepare($sql);
$q->execute();
$resources = $q->fetchAll(PDO::FETCH_ASSOC);
foreach ($resources as $row) {
    $resource = $modx->getObject('modResource', $row['category_id']);
    $result[] = '<a href="'.$modx->getOption('site_url').$resource->get('uri').'">'.$resource->get('pagetitle').'</a>';
   	
}
return implode($delimeter, $result);
    Роман
    18 октября 2021, 11:40
    0
    Попробуйте строку:
    $url = $modx->makeUrl($row['id'], '', '', $scheme);
    заменить на:
    $url =  '/' . $row['uri'];
      Роман
      18 октября 2021, 11:41
      0
      Павел, сорри, не в ту ветку написал.
      Сергей Шлоков
      18 октября 2021, 14:47
      0
      Запрос в БД в цикле — плохой вариант.
      Сергей Шлоков
      18 октября 2021, 15:09
      0
      Во-первых, ограничивайте количество в запросе, а не тащите всю таблицу в PHP.
      Во-вторых, у таблицы msCategoryMember нет индекса для связи с таблицей категории (ресурсов). Попробуйте добавить.
        kgb3000
        18 октября 2021, 20:17
        0
        Спасибо за подсказки. Решил следующим образом

        <?php
        if (empty($rid)) {$rid = $modx->resource->id;}
        if (empty($pid)) {$pid = $modx->resource->parent;}
        if (empty($delimeter)) {$delimeter = ' / ';}
        
        $parent = $modx->getObject('modResource', $pid);
        $output[] = '<a href="'.$parent->get('uri').'">'.$parent->get('pagetitle').'</a>';
        
        $pdo = $modx->getService('pdoFetch');
        
        $conditions = array('product_id' => $rid);
        
        $options = array(
        	'innerJoin' => array(
        		'msCategory' => array('on' => 'msCategoryMember.category_id = msCategory.id')
        	),
        	'select' => array('msCategory' => 'all'),
        	'sortby' => 'msCategory.id'
        );
        $rows = $pdo->getCollection('msCategoryMember', $conditions, $options);
        
        
        foreach ($rows as $row) {
        	$output[] .= '<a href="'.$row['uri'].'">'.$row['pagetitle'].'</a>';
        }
        
        return implode($delimeter, $output);
          Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
          6