Работа с prepareSnippet

Доброго времени суток!

Пытаюсь на своем сайте сделать все правильно, а именно вызывать pdoPage сразу с шаблоном, и обрабатывать данные заранее, через prepareSnippet. Но самостоятельно, у меня ничего не выходит — не хватает опыта. Подскажите, что делаю неправильно.

Сейчас на сайте работает (но очень медленно, из за кол-ва ненужных запросов, если я правильно все понял) вот так:

Вызов pdoPage

[[!pdoPage:default=`<div class=\"fool\"><p>К сожалению, товары с указанными параметрами отсутствуют. За помощью в подборе, Вы можете обратиться по телефону <span>+7(xxx) xxx-xx-xx</span>.</p></div>`?sortby=`Data.price`  
	&element=`msProducts` 
	&parents=`2`
	&showLog=`1`
	&tpl=`tpl.msProducts.row`
	&limit=`72`
]]

Сам tpl.msProduct.row, в котором вызывается порядка 5 сниппетов

<div class="container_cat-item">	
	<div class="cat-item">
		<div class="catalogue-in">
			<div class="catalogue-item catalogue-item_hover">
				<a href="[[~[[+id]]]]" target="_blank" class="cat-item"><img class="lazy"  data-original="[[!imgGet? &pId=`[[+id]]` &key=`0`]]" height="130"></a>
				<span class="cat-sku">[[+wl]]x[[+rad]] [[+co]]х[[+pcd]] [[+dl]] ET[[+vl]]</span>
    			<div class="floater">	
    				<h3 class="cat-item">
    					<a href="[[~[[+id]]]]" target="_blank" class="cat-item">[[+pagetitle]]</a>
    				</h3>
    			</div>
				<div class="price">
					<span class="price_val">[[+price]]</span>
					<span class="price_cur">руб.</span>
				</div>
				<div class="cat_down">
    			    <form method="post" class="ms2_form">    
    				    [[!getBtn? &id=`[[+id]]`]]
    				    <input type="hidden" name="id" value="[[+id]]">
    			        <input type="hidden" name="count" value="4">
    			        <input type="hidden" name="options" value="[]">
    			    </form>
    			    [[!getTip? &id=`[[+id]]`]]
				</div>
			</div>
			<div class="catalogue-item catalogue-item_descr">
				<a href="" class="cat-logo">[[!getMade? &id=`[[+id]]` ]]</a>
				<table class="cat_params">
					<tbody>
						<tr>
							<td>Тип диска</td>
							<td class="params_val">[[!getType? &id=[[+id]] ]]</td>
						</tr>
						<tr>
							<td>Ширина литья</td>
							<td class="params_val">[[+wl]] дм</td>
						</tr>
						<tr>
							<td>Диаметр</td>
							<td class="params_val">[[+rad]] дм</td>
						</tr>
						<tr>
							<td>Разболтовка (PCD)</td>
							<td class="params_val">[[+co]]х[[+pcd]]</td>
						</tr>
						<tr>
							<td>Диаметр ступицы</td>
							<td class="params_val">[[+dl]] мм</td>
						</tr>
						<tr>
							<td>Вылет литья (ЕТ)</td>
							<td class="params_val">[[+vl]] мм</td>
						</tr>
					</tbody>
				</table>
				<div class="cat_descript">
			        [[!getMadeText? &id=`[[+id]]` ]]
				</div>
			</div>
		</div>
	</div>
</div>

И код сниппета getBtn (на его примере рассмотрю)

<?php
$id = $scriptProperties['id'];
$key = $scriptProperties['key'];

if ($product = $modx->getObject('msProduct', $id)) {
	$res = $product->get('bal');
	//echo $res;
	if ($res < 4 && !empty($res)) {
	    echo "<button class=\"btn2 btn_grey\" type=\"submit\" id=\"nocart\" name=\"ms2_action\" >Не комплект</button>";
	    if ($key == 1) {
	        echo "
	        </div>
            <div class=\"wait\">
                <p><b>Готовы подождать?</b></p>
                <p>Оставьте минимум контактной информации <a class=\"inline cboxElement\" href=\"#inline_content2\">здесь</a>, и наши менеджеры свяжутся с вами, как только товар поступит в наличие.</p>
            </div>";
	    }
	} else if (empty($res)) {
	     echo "<button class=\"btn2 btn_grey\" type=\"submit\" id=\"nocart\" name=\"ms2_action\" >Нет в наличии</button>";
	     if ($key == 1) {
	        echo "
	        </div>
            <div class=\"wait\">
                <p><b>Готовы подождать?</b></p>
                <p>Оставьте минимум контактной информации <a class=\"inline cboxElement\" href=\"#inline_content2\">здесь</a>, и наши менеджеры свяжутся с вами, как только товар поступит в наличие.</p>
            </div>";
	    }
	} else {
	     if ($key == 1) {
	        echo "<button class=\"btn2 btn_orange\" type=\"submit\" name=\"ms2_action\" value=\"cart/add\">В корзину</button></div>"; 
	     } else {
	        echo "<button class=\"btn2 btn_orange\" type=\"submit\" name=\"ms2_action\" value=\"cart/add\">В корзину</button>";  
	     }
	}
}

Пытаюсь самостоятельно привести все к нормальному виду вот так, т.е. вызов pdoPage

[[!pdoPage:default=`<div class=\"fool\"><p>К сожалению, товары с указанными параметрами отсутствуют. За помощью в подборе, Вы можете обратиться по телефону <span>+7(xxx) xxx-xx-xx</span>.</p></div>`?
	&sortby=`Data.price`  
	&element=`msProducts` 
	&parents=`2`
	&showLog=`1`
	&limit=`72`
	&prepareSnippet=`testSnippet`
	&tpl=`@INLINE
	<div class='container_cat-item'>	
		<div class='cat-item'>
			<div class='catalogue-in'>
				<div class='catalogue-item catalogue-item_hover'>
					<a href='[[~[[+id]]]]' target='_blank' class='cat-item'><img class='lazy'  data-original='[[!imgGet? &pId=`[[+id]]` &key=`0`]]' height='130'></a>
					<span class='cat-sku'>[[+wl]]x[[+rad]] [[+co]]х[[+pcd]] [[+dl]] ET[[+vl]]</span>
					<div class='floater'>	
						<h3 class='cat-item'>
							<a href='[[~[[+id]]]]' target='_blank' class='cat-item'>[[+pagetitle]]</a>
						</h3>
					</div>
					<div class='price'>
						<span class='price_val'>[[+price]]</span>
						<span class='price_cur'>руб.</span>
					</div>
					<div class='cat_down'>
						<form method='post' class='ms2_form'>    
							[[+getBtn]]
							<input type='hidden' name='id' value='[[+id]]'>
							<input type='hidden' name='count' value='4'>
							<input type='hidden' name='options' value='[]'>
						</form>
						[[+getTip]]
					</div>
				</div>
				<div class='catalogue-item catalogue-item_descr'>
					<a href='' class='cat-logo'>[[+getMade]]</a>
					<table class='cat_params'>
						<tbody>
							<tr>
								<td>Тип диска</td>
								<td class='params_val'>[[+getType]]</td>
							</tr>
							<tr>
								<td>Ширина литья</td>
								<td class='params_val'>[[+wl]] дм</td>
							</tr>
							<tr>
								<td>Диаметр</td>
								<td class='params_val'>[[+rad]] дм</td>
							</tr>
							<tr>
								<td>Разболтовка (PCD)</td>
								<td class='params_val'>[[+co]]х[[+pcd]]</td>
							</tr>
							<tr>
								<td>Диаметр ступицы</td>
								<td class='params_val'>[[+dl]] мм</td>
							</tr>
							<tr>
								<td>Вылет литья (ЕТ)</td>
								<td class='params_val'>[[+vl]] мм</td>
							</tr>
						</tbody>
					</table>
					<div class='cat_descript'>
						[[+getMadeText]]
					</div>
				</div>
			</div>
		</div>
	</div>
	`
]]

И код одного из сниппетов в prepareSnippet (testSnippet)

<?php
$modx->setPlaceholder('getBtn', $row['getBtn']);
$id = $scriptProperties['id'];
$key = $scriptProperties['key'];

if ($product = $modx->getObject('msProduct', $id)) {
	$res = $product->get('bal');
	if ($res < 4 && !empty($res)) {
	    $row[`getBtn`] .= "<button class=\"btn2 btn_grey\" type=\"submit\" id=\"nocart\" name=\"ms2_action\" >Не комплект</button>";
	    if ($key == 1) {
	        $row[`getBtn`] .= "
	        </div>
            <div class=\"wait\">
                <p><b>Готовы подождать?</b></p>
                <p>Оставьте минимум контактной информации <a class=\"inline cboxElement\" href=\"#inline_content2\">здесь</a>, и наши менеджеры свяжутся с вами, как только товар поступит в наличие.</p>
            </div>";
	    }
	} else if (empty($res)) {
	     $row[`getBtn`] .= "<button class=\"btn2 btn_grey\" type=\"submit\" id=\"nocart\" name=\"ms2_action\" >Нет в наличии</button>";
	     if ($key == 1) {
	        $row[`getBtn`] .= "
	        </div>
            <div class=\"wait\">
                <p><b>Готовы подождать?</b></p>
                <p>Оставьте минимум контактной информации <a class=\"inline cboxElement\" href=\"#inline_content2\">здесь</a>, и наши менеджеры свяжутся с вами, как только товар поступит в наличие.</p>
            </div>";
	    }
	} else {
	     if ($key == 1) {
	        $row[`getBtn`] .= "<button class=\"btn2 btn_orange\" type=\"submit\" name=\"ms2_action\" value=\"cart/add\">В корзину</button></div>"; 
	     } else {
	        $row[`getBtn`] .= "<button class=\"btn2 btn_orange\" type=\"submit\" name=\"ms2_action\" value=\"cart/add\">В корзину</button>";  
	     }
	}
}
return serialize($row);

Но у меня ничего не выходит. Шаблон выводится, но ни один из сниппетов не работает.
Знаю, что скорее всего пишу какую-то ересь, но очень сложно это дается. Укажите, пожалуйста, на ошибки.
Пашкович Дмитрий
20 октября 2014, 09:06
modx.pro
3
4 203
0

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

Володя
20 октября 2014, 13:20
0
не надо в INLINE пихать то что у вас… делайте обычным шаблоном
    Василий Наумкин
    20 октября 2014, 13:30
    +2
    В чанке заменяешь
    [[!getBtn? &id=`[[+id]]`]]
    на
    [[+getBtn]]
    То есть, вместо вызова сниппета будет плейсхолдер, куда потом вставится результат.

    Затем в сниппете, указанном в prepareSnippet пишешь эту свою логику определения не получая ресурс — он уже получен и находится в переменной $row!
    <?php
    $id = $row['id'];
    $key = $row['key']; // Не знаю, что это - надеюсь, что поле ресурса
    
    $res = $row['bal'];
    if ($res < 4 && !empty($res)) {
    	$row['getBtn'] .= "<button class=\"btn2 btn_grey\" type=\"submit\" id=\"nocart\" name=\"ms2_action\" >Не комплект</button>";
    	// ... тут остальная твоя логика, цель которой выставить верный $row['getBtn']
    }
    // Serialize может проглючивать, замечал такое. Если что - пробуй еще
    // return json_encode($row);
    return serialize($row);
    В итоге мы не получаем ресурс из БД повторно, не делаем некаких запросов, а только добавляем новое поле в массив данных, проверяя другие поля этого массива — что в итоге будет вставлено в чанк.

    Никаких getObject и setPlaceholder не нужно — именно от них мы и избавляемся для большей скорости.

    То есть, всё уже выбрано, ты просто подготавливаешь массив данных для оформления в чанке. Отсюда и название параметра — «подготовочный сниппет».
      Пашкович Дмитрий
      20 октября 2014, 13:33
      0
      Сейчас буду пробовать, огромное спасибо!
        Василий Наумкин
        20 октября 2014, 13:36
        1
        0
        Ты для начала попробуй простой пример:
        [[!pdoResources?
        	&tpl=`@INLINE <a href="/[[+uri]]">[[+pagetitle]]</a>`
        	&parents=`0`
        	&prepareSnippet=`mySnippet`
        ]]
        Сниппет mySnippet:
        $row['pagetitle'] .= rand();
        
        return serialize($row);

        Дальше уже усложняй и добавляй свою логику, чанки и код из сниппетов.
          Пашкович Дмитрий
          20 октября 2014, 14:21
          0
          Для первого сниппета сработало, для того, которого я показал в примере (getBtn).
          Все как Вы и писали, только дополнено:

          <?php
          $id = $row['id'];
          $key = $row['key'];
          
          // 1
          $res = $row['bal'];
          if ($res < 4 && !empty($res)) {
          	$row['getBtn'] .= "<button class=\"btn2 btn_grey\" type=\"submit\" id=\"nocart\" name=\"ms2_action\" >Не комплект</button>";
          	if ($key == 1) {
          	        $row['getBtn'] .= "
          	        </div>
                      <div class=\"wait\">
                          <p><b>Готовы подождать?</b></p>
                          <p>Оставьте минимум контактной информации <a class=\"inline cboxElement\" href=\"#inline_content2\">здесь</a>, и наши менеджеры свяжутся с вами, как только товар поступит в наличие.</p>
                      </div>";
          	    }
          	} else if (empty($res)) {
          	     $row['getBtn'] .= "<button class=\"btn2 btn_grey\" type=\"submit\" id=\"nocart\" name=\"ms2_action\" >Нет в наличии</button>";
          	     if ($key == 1) {
          	        $row['getBtn'] .= "
          	        </div>
                      <div class=\"wait\">
                          <p><b>Готовы подождать?</b></p>
                          <p>Оставьте минимум контактной информации <a class=\"inline cboxElement\" href=\"#inline_content2\">здесь</a>, и наши менеджеры свяжутся с вами, как только товар поступит в наличие.</p>
                      </div>";
          	    }
          	} else {
          	     if ($key == 1) {
          	        $row['getBtn'] .= "<button class=\"btn2 btn_orange\" type=\"submit\" name=\"ms2_action\" value=\"cart/add\">В корзину</button></div>"; 
          	     } else {
          	        $row['getBtn'] .= "<button class=\"btn2 btn_orange\" type=\"submit\" name=\"ms2_action\" value=\"cart/add\">В корзину</button>";  
          	     }
          	}
          return serialize($row);

          Но дальше, (перед return serialize($row);) пытаюсь вставить код следующего сниппета, так же убрав запросы и подставив $row в нужное место

          $res = $row('made');
          	if ($res == "LS") {
          	    $row['getMade'] .= "<img class=\"made_product location\" src=\"img/ls_logo.png\" title=\"«LS Alloy wheels». Страна производитель: Тайвань, Китай\">";
          	} else if ($res == "Replay") {
          	    $row['getMade'] .= "<img class=\"made_product location\" src=\"img/replay_logo.png\" title=\"«Replay». Производство на заводах Тайване, Турции, Италии и КНР. Это модели, параметры которых максимально близки к параметрам дисков известных мировых брендов, таких как Mercedes, Ford, Mazda, Audi, Mitsubishi, Nissan BMW, и многих других, они сохраняют абсолютно все параметры оригинальных изделий.\">";
          	} else if ($res == "TG Racing") {
          	    $row['getMade'] .= "<img class=\"made_product location\" src=\"img/tgracing_logo.png\" title=\"«TG Racing». Страна производитель: Китай. Марка принадлежит корпорации «Lizhong Wheel Group»,  ведущей  компании по производству легкосплавных колес в Азии. Официальный представитель в России - ООО «Компания Алтан ДВ»\">";
          	} else if ($res == "Nitro") {
          	    $row['getMade'] .= "<img class=\"made_product location\" src=\"img/nitro_logo.png\" title=\"«Nitro». Страна производитель: Китай\">";
          	} else if ($res == "Enkei") {
          	    $row['getMade'] .= "<img class=\"made_product location\" src=\"img/enkei_logo.png\" title=\"«ENKEI». Страна производитель: Китай\">";
          	} else if ($res == "Rw") {
          	    $row['getMade'] .= "<img class=\"made_product location\" src=\"img/rw_logo.png\" title=\"«RW». Страна производитель: Китай\">";
          	} else if ($res == "Nz") {
          	    $row['getMade'] .= "<img class=\"made_product location\" src=\"img/nz_logo.png\" title=\"«NZ». Страна производитель: Китай\">";
          	} else if ($res == "Konig") {
          	    $row['getMade'] .= "<img class=\"made_product location\" src=\"img/konig_logo.png\" title=\"«Konig». Страна производитель: Китай\">";
          	} else if ($res == "Ijitsu") {
          	    $row['getMade'] .= "<img class=\"made_product location\" src=\"img/ijitsu_logo.png\" title=\"«Ijitsu». Страна производитель: Китай\">";
          	} else if ($res == "IJI") {
          	    $row['getMade'] .= "<img class=\"made_product location\" src=\"img/iji_logo.png\" title=\"«IJI». Страна производитель: Китай\">";
          	}

          Как результат — пустая страница, ошибка. Как в prepare включить все сниппеты разом?
            Василий Наумкин
            20 октября 2014, 14:26
            0
            $res = $row('made');
            Так к ключам массивов не обращаются. Это error.
              Пашкович Дмитрий
              20 октября 2014, 15:20
              0
              $res = array($row['made']);
              Так?
                Василий Наумкин
                20 октября 2014, 15:23
                1
                0
                Да, блин, включи логику!

                Рабочий код
                $res = $row['bal'];
                Нерабочий код
                $res = $row('made');

                Чем отличается рабочий код от нерабочего? Что нужно исправить?
    Пашкович Дмитрий
    20 октября 2014, 15:44
    0
    Сделал, все получилось. Время загрузки сократилось до 1.1 секунды. Василий, скажите, а если вынести шаблон в вызов pdoPage, скорости не прибавится?
    Ну в любом случае огромное Вам спасибо за то, что откликнулись и помогли!
      Василий Наумкин
      20 октября 2014, 16:00
      0
      Ты о том, чтобы INLINE чанк превратить в обычный?

      В принципе, да, это может совсем чуть-чуть сократить время загрузки, потому что парсер MODX не будет пытаться разобрать инлайновый чанк и плейсхолдеры в нём.

      Но в целом, думаю, тебе нужно оптимизировать вызовы других сниппетов на странице. Можно воспользоваться для этого моим дополнением debugParser.
        Пашкович Дмитрий
        20 октября 2014, 16:03
        0
        Сейчас попробую тогда.
        Еще одна мелочь, наверное опять туплю. Никак не могу обозначить $row для этой логики

        $images = $modx->getCollection('msProductFile', array('product_id' => $pId, 'type' => 'image', 'rank' => $key, 'parent' => 0));
        foreach ($images as $image) {
            echo $image->get('url');
        }
        if (empty($images)) {echo "img/noimage.png";}
          Василий Наумкин
          20 октября 2014, 16:10
          1
          0
          msProducts сразу выбирает картинки, если указан &includeImages и точно так же позволяет указывать prepareSnippet.

          Используй его и картинки уже будут в $row. Вообще, посмотри, что сейчас там есть:
          echo '<pre>';print_r($row);die;
            Пашкович Дмитрий
            20 октября 2014, 16:26
            0
            Не получается, я наверное даже Вас не понял(
            Опыта не хватает, с первого раза понять то, что вы пишете, или мозгов.

            $images = $row['includeImages'];
            foreach ($images as $image) {
                $row['imgGet'] .= $image->get('url');
            }
            if (empty($images)) {$row['imgGet'] .= "img/noimage.png";}

            я так понимаю, это совсем не то, что Вы имели ввиду?
              Пашкович Дмитрий
              20 октября 2014, 17:45
              0
              Никак не получается, попробовал все, на что мозгов хватило. Подскажите, что не так делаю?
                Василий Наумкин
                20 октября 2014, 17:53
                0
                Не images, а thumbs — я ошибся. Но в любом случае, ты меня вообще не понял:
                [[!msProducts?
                	&includeThumbs=`120х90`
                	&parents=`0`
                	&prepareSnippet=`твойсниппет`
                ]]

                Внутри $row должна быть ссылка на картинку товара:
                echo $row['120x90']; die;
                  Пашкович Дмитрий
                  20 октября 2014, 18:19
                  0
                  Если я правильно все понял, то !msProducts я вызываю вместо этого, в чанке

                  [[!imgGet? &pId=`[[+id]]` &key=`0`]]

                  А prepare делаю еще один, где размещаю вот это

                  echo $row['120x90']; die;
                  Не совсем понимаю и как ссылку разместить. Внутри скобок [[~[[+id]]]]?

                  Прощу прощения, если раздражаю, просто уже ум за разум заходит
                    Василий Наумкин
                    20 октября 2014, 18:49
                    0
                    Дима, мне сколько раз нужно повторить, что мы не выбираем ничего дополнительно?

                    Объясняю так, чтобы ты понял:
                    [[!pdoPage:default=`<div class=\"fool\"><p>К сожалению, товары с указанными параметрами отсутствуют. За помощью в подборе, Вы можете обратиться по телефону <span>+7(xxx) xxx-xx-xx</span>.</p></div>`?sortby=`Data.price`  
                    	&element=`msProducts` 
                    	&parents=`2`
                    	&showLog=`1`
                    	&tpl=`tpl.msProducts.row`
                    	&limit=`72`
                    	&includeThumbs=`120х90`
                    	&prepareSnippet=`твойсниппет`
                    ]]
                    Дошло?

                    Нужно просто попросить msProducts вместе с твоими товарами выбрать им картинки — он это умеет. А дальше делай с ними что хочешь в prepareSnippet.

                    Вместо
                    [[!imgGet? &pId=`[[+id]]` &key=`0`]]
                    пиши
                    [[+120x90]]

                    Я не знаю, как еще объяснить. bezumkin.ru/modx/minishop2/snippets/917/
                      Пашкович Дмитрий
                      20 октября 2014, 18:59
                      0
                      Логика процесса наконец дошла, доползла.
                      Вот этого только не понял.
                      Внутри $row должна быть ссылка на картинку товара:
                      Все делаю так, как Вы сказали, но картинок нет.

                      Помоему у меня картинки заливаются в gallery
        Алексей Шумаев
        20 мая 2016, 10:11
        0
        Василий, а можно ли prepareSnippet передавать некие дополнительные параметры? Если да, то как?
        Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
        23