11 янв. 2015 г., 12:21

Как отрубить работу шаблона в середине него (аналог die($res) в сниппетах)

Возможно ли в смарти шабонах прервать отрабтку оног, как в сниппете die($res)? Объясню, что я хочу. Тем более, что пишу на половину, чтобы рассказать о удобном методе работы с ajax, пусть и не идеальном. Хотя все решаетцо наверняка очень просто и меня щас будут стыдить, что мало читал доки по смарти и т.д. ))) Есть старый добрый метод аджаксоделанья, когда на верх шаблона вставляешь сниппет
// если в заголовке XMLHttpRequest, как при ajax-запросах методом jquery, то работаем, нет - сниппет вырубаетцо. if ($_SERVER['HTTP_X_REQUESTED_WITH'] != 'XMLHttpRequest') {return;} // что-нибудь возвращаешь $res = 'Hello World!'; // прерываешь работу шаблона die($res);
Там в сниппете мы должны были отдать какой-то контент. А как мы получаем и отдаем контент в смарти-шаблонах? Ну получаем через $smarty.request/$smarty.post/$smarty.get соответствующим образом переданные параметры (или не принимаем), набиваем их в массив через assign, передаем в процессор и отображаем результат. И все это можно вынести в отдельный темплейт и отображать в шаблоне страницы как-то так {include file=«inc/shop/product.tpl»} Ну и как можно модернизировать сниппет выше в смарти-виде?
{if $smarty.server.HTTP_X_REQUESTED_WITH == 'XMLHttpRequest'} {include file="inc/shop/product.tpl"} {else} содержание шаблона. {/if}
Теперь отправляем нужные параметры на страницу $.ajax — и понеслось. И заменяем полученный результат на тот, что в нашем (это метод $.ajax)
success: function (data) { $('.ajax-block').replaceWith(data); }
Собственно прелесть в том, что за отображение на сайте и возвращения аджаксом отвечает один шаблон и любые изменения в первом автоматически же отражаются и во-втором. Конечно, кто-то возразит, что дергать конечный html это не тру и трафика много тратится. Но это просто ооочень удобный метод, который с шаблонами смарти становится намного удобнее. Конечно, в сниппете это тоже можно было имитировать, но выводом аджакса и отображением на сайте нужно было заниматься отдельно. Собственно в чем вопрос. В сниппете мы могли написать die($res); и отработка шаблона прекратилась, а нам бы вернулось то, что есть. В смарте же такое не канает? Шабоны в смарти наследуются, но такой блок, чтобы вверху было
{if $smarty.server.HTTP_X_REQUESTED_WITH == 'XMLHttpRequest'} {include file="inc/shop/product.tpl"} // от здесь бы прерывать отрисовку шаблона {else} содержание шаблона. {/if}
неудобно. Может быть можно как-то похожем образом прервать выполнение шабона, чтобы он остановился? А то приходится в главном layout.tpl писать if-else конструкцию. А это не очень хорошо и не очень удобно.
UPD Если для кому неудобно обертывать весь родительский лейаут в if, то можно сделать плагин на OnWebPageInit и условиями
if ($modx->event->name == 'OnWebPageInit' AND $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') { // Получаем ресурс if (!is_object($modx->resource)) { $modx->resource = $modx->request->getResource($modx->resourceMethod, $modx->resourceIdentifier); } ..........
Ну, и конечно + определяем id и прочие ваши проверки. Но это не так удобно т.к. невозможно переопрделить отдаваемое содержимое в зависимости от шаблона. Зато понимаш, без обертки if :)
можно в контроллере прописать
$modx->smarty->allow_php_tag = true;
и в шаблоне тогда можно будет вставить
{php} die; {/php}
Спасибо. Попробую.
На сколько я знаю, нет в смарти ни exit, ни die, ни даже return. Поэтому хочется или нет, но придется юзать if/else.
Саш, а ты проверял на практике? Ведь здесь не все так просто. Частичный вывод контента и т.п. По-моему не проканает нормальной работы.
Все-таки я пока остановился на таком механизме: modxclub.ru/topics/ajax-katalog-na-praktike-1258.html Конечно и он не идеальный, но в целом очень даже работоспособный. Ведь не весь сайт нужен для подгрузки, а только какие-то определенные разделы. И вообще, в современных JS-либах подгружают весь контент страницы, просто из всего полученного контента выдергивают нужные Ajax-блоки и вставляют куда надо (реализуется просто на уровне таг-селекторов).
Интересная идея я сейчас с этим работаю. У меня задача при штатном переходе на сайт загружать страницу нормально шаблоном. А далее все переходы по ссылкам в внутри сайта перехватываются JS Ext и тот должен запросить по ссылке Json данные страницы и перестроить страницу.
Плагины не подходят?
Чет не получилось у меня вырвать конструкцию if/else с проверкой на HTTP_X_REQUESTED_WITH из основного, всеми наследуемого layout.tpl.
Просто хочется, чтобы в нем этой конструкции и проверки вообще небыло.
Пробуй наследовать другой (пустой) layout, на основании проверки на HTTP_X_REQUESTED_WITH…
Наследование прописывается в шапке файла. {extends ...}. Нельзя по условию наследовать. Но можно по условию инклюдить файлы-шаблоны.
В общем, я пробовал по всякому. Ничего нормального тут не получается. Но поделюсь одним нестабильным элементом:
Весь главный шаблон оборачиваем в блок, к примеру resource.
Далее создаем новый промежуточный layout-wraper.tpl с таким содержимым
{extends "layout.tpl"} {block name="resource"} {if $is_ajax} {block name=content} {$smarty.block.parent} {/block} {else} {$smarty.block.parent} {/if} {/block}
Здесь важно, чтобы блока content не было в главном layout-шаблоне. Вот тогда при вызове какого-либо более глубокого расширяемого шаблона по условию выводился только блок content. Но у меня это было очень не стабильно. Это скорее бага, чем фича. Если захочешь с этим поэкспериментировать, то до конечного шаблона создай еще один расширяющий шаблон, в котором будет только расширение прописано {extends ...} и все. Мне сейчас совсем некогда ковырять глубоко Смарти, чтобы объяснить такое странное его поведение. Коммент оставляю, чтобы возможно на досуге вернуться к изучению этого интересного явления.
В Smarty в {extends ....} можно использовать переменную, примерно так: {extends $modx->layout}
а $modx->layout можно где-нибудь определить
скажем в modxsmarty.class.php в конструкторе:
... ... function __construct(modX &$modx, $params= array ()) { parent :: __construct(); $this->modx= & $modx; $this->modx->layout= $_SERVER['HTTP_X_REQUESTED_WITH'] != 'XMLHttpRequest' ? "layout.tpl" : "<strong>empty_layout.tpl</strong>"; ... ...
сам не проверял…
да, правда только в верхнем layout. поставил перед футером — отсекает. правда, тоже нет — сейчас посмотрел :(
Надо просто учитывать, что в отличие от return где-нибудь в блоке присвоения значений в php-коде, в смарти это буквально в блоке вывода echo/print, из-за чего мы обламываем таким образом процесс вывода, а не процесс присвоения.
Да, указать переменную шаблона действительно можно, просто из прошлого коммента подумалось типа {if}{extends ...}{else}..{/if}. Такое там не канает. А с переменной получается следующее:
1. В __construct лезть не оязательно, у нас же за все отвечает единый контроллер base.php
Прописываем в нем условие:
<?php // .................................. if($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest'){ $modx->setOption('layout', 'ajax-layout.tpl'); $compile_id = 'ajax'; } else{ $modx->setOption('layout', 'layout.tpl'); $compile_id = 'layout'; } return $modx->smarty->fetch("tpl/{$tpl}", '', $compile_id);
Обязательно задаем разные $compile_id, иначе не будет перекомпиливаться уже отработанный шаблон.
2. Создаем ajax-layout.tpl В нем пишем:
{block name=content} {$modx->resource->content} {/block}
3. Создаем промежуточный switch-layout.tpl, с содержимым:
{extends $modx->getOption('layout', null, 'layout.tpl')}
Здесь один минус есть: в рабочем режиме у шаблонов переменная phptemplates.non-cached == false, и Smarty-шаблоны при повторном заходе не отрабатываются. Так что придется некеширование выставлять в true, что конечно же скажется на производительности. Можно конечно в настройках modxSmarty включить кеширование самих смарти-шаблонов, но это усложняет разработку, ибо надо будет более четко продумывать где что кешировань/не кешировать, и прописывать где надо nocache. Но если это правильно использовать, то нагрузка не должна увеличиться так, чтобы заметно было.
P.S. За полезный коммент поднимаю права до члена Клуба :)
Лезть в modxsmarty.class.php — это перебор. Короче if/else в главном лейауте остается пока самым простым и железобетонным способом.
Я выше написал как без этого храдкода.
Но вы же говорите, что и там это «скорее баг»?
Нет. Про баг — это здесь. А переменная в {extended ...} — это стабильный вариант. Просто как я и сказал, надо с кешированием быть повнимательней.
Извиняюсь, не на тот комент подумал. но там тоже не все гладко. Хотя как инфа к размышлению интересно.
Все ништяк с аджаксом, но скрипты shopmodx теряются. После первого взгляда на скрипты понимаешь — их куча Кажется, что разбираться с ними придется долго и т.д. Но вроде бы работает такая махинация: Напомню, что в нашем лейауте вот такая конструкция
{if $smarty.server.HTTP_X_REQUESTED_WITH == 'XMLHttpRequest'} {include file="inc/shop/product.tpl"} // от здесь бы прерывать отрисовку шаблона {else} содержание шаблона. {/if}
{include file=«inc/shop/product.tpl»} так же висит в категории товаров и собственно его мы и отображаем. Добавляем в product.tpl скрипты из шапки. И не забудем указать в $.ajax указать dataType: «multiple», чтобы при аджакс-загрузках не отрубались js. Теперь все ништяк, после аджакс-обновления страницы товары в корзину добавляются, но дважды )) Нужно удалить скрипты из головы страницы. И конечно их нужно обязательно добавить в шаблон с корзиной, чтобы она тоже работала. С локалки еще не перенес, тестил пока только в Огнелисе, но выглядит прикольно. И по-идеи должно работать везде. Кстати, выяснилось, что скрипты ШопМодихса не работают в ie6 ))) Т.о. можно делать фильтры любой сложности, любого вида и на аджаксе. Разве что в скобках можно еще указывать количества товаров при выборе разных опций. Но я этим не заморачиваюсь, хотя наверняка это было бы можно.
Нда, скрипты обрезались. Ну, вы поняли.
Кстати, выяснилось, что скрипты ШопМодихса не работают в ie6 )))
Шестой осел уж не первый год как похоронен. О чем вы?
Покликай каталог и корзину здесь: termasol.ru.modxdev.webtm.ru/products/heating/fireplace/ Не все еще сделано, но в целом работает. Корзина там более прокаченная.
Чессказать даже в исходном тексте сообщения все пусто в в листинге. Выложи на гист то, что ты там писал. Я посмотрю почему вырезалось.
Странно… Погоняю на досуге
Я так и подумал на них. Вообще MODX вырезает скрипты из запросов. Но посмотрю, может и решу этот вопрос.
Кстати, выяснилось, что скрипты ШопМодихса не работают в ie6 )))
На дворе 2015 год. Уже 8 осел бессмысленно поддерживать, а вы все над хладным телом шестого глумитесь…
Я между прочим с тела виндо-хр пишу ) Но про ie6 я не серьезно.

Добавить комментарий