7 февр. 2015 г., 8:23

Этика кода modxSmarty, phpTemplates, modxSite

Недавно в одной из моих тем-вопросов (про Update рабочего сайта) Вы рассказали про интересный плагин. Чесно сказать загорелся. Сейчас готов к переводу существующего проекта ну примерно процентов на 70%. Осталось выяснить как же правильно реализовать некоторые моменты.
Генерирование таблиц на основе данных БД. как это сейчас есть сниппет showTable с параметром tablecontent в сниппете на основании этого параметра на первом этапе делается выборка данных и генерируются строки таблицы.
$rows .= $modx->getChunk('chunk', $params);
на втором этапе генерируется непосредственно таблица
/* * @params thead , rows */ $output = $modx->getChunk('table', $params);
на каждую таблицу приходится 2 собственных чанка (thead, rows) и один обвертка для таблицы (table)
Вопрос заключается в том как это красиво должно быть реализовано в новой среде. Хотелось бы собрать таблицу непосредственно в шаблоне.
Для этого достаточно в шаблон заглянуть, допустим в формировании таблицы товаров в письме клиенту. если ты получил данные в массив, скажем $params, дальше по стандарту. для этого понадобится перебрать массив {foreach $params.rows as $rows}
<table border="0" cellpadding="5" cellspacing="3" style="width:100%;border-collapse:separate;"> <tbody> {foreach $order_data.object as $product} <tr> <td style="width:170px;border-bottom:1px solid #ccc;"><img src="{$site_url}{snippet name=phpthumbof params="input=`{$Path}upload/photos/{$product.sm_article}_0.jpg`&options=`w=120&h=120&zc=0`"}"></td> <td style="background:#eee;"> <u>{$product.pagetitle}</u> Артикул: {$product.sm_article} Количество: {$product.quantity} Размер: {str_replace('S_','',$product.size)} Цена: {$product.price} руб. </td> </tr> {/foreach} <tr> <td><b>Стоимость доставки</b></td> <td style="background:#eee;"><b>{$properties.delivery} руб.</b></td> </tr> <tr> <td><b>Общая сумма заказа</b></td> <td style="background:#eee;"><b>{$order_data.sum + $properties.delivery} руб.</b></td> </tr> </tbody> </table>
откуда рождается в примере $order_data.object? сниппеты вроде как не могут возвращать ничего кроме строк
Зато процессоры могут возвращать массив. Все зависит от ситуации, письмо формируется в запросе из процессора submit $this->modx->smarty->fetch($tpl), и массивы с переменными подключаются заранее $this->modx->smarty->assign('order_data', $data);
процессоры не принимают параметры. значить, получатся для каждой таблицы придется создавать свой процессор
Кто такое сказал? Вот 2 примера по реализации. В обоих случаях результат вернет в переменную $result.
{assign var = params value = [ "limit" => 30, "getPage" => 1, "query" => {$smarty.get.query} ]} {*processor action="web/catalog/category/products/getdata" ns="modxsite" params="limit=`30`&getPage=`1`" assign=result*} {processor action="web/filter/catalog" ns="modxsite" params=$params assign=result}
сниппеты вроде как не могут возвращать ничего кроме строк
Вот поэтому мы сниппеты и не используем (на самом деле не только по этому, но на самом деле иногда все-таки используем, к примеру, для вызова некешируемого Смарти-блока тип [[!smarty?tpl=`....tpl`]]).
Можно и лучше даже так:
{$params = [ "limit" => 30, "getPage" => 1, "query" => $smarty.get.query ]}
Это я из старого шаблона взял, еще ShopModxBox 2.0 :)
спасибо за ответы. отличная картина вырисовывается :)
продолжим… проект постепенно переходит на новый уровень (пока только на черновиках) а мы продолжаем наращивать заветные проценты. сегодня на повестке для, и имеем мы дело с фротн-эндом:
Опять же таблица. Есть процессор getServiceList его задача подключится к таблице my_table в бд и считать от туда информацию. Вопрос в том как в этот процессор корректно загнать MODX API, ведь хочется получить все вкусняшки, ранее все это делалось через сниппет, но поскольку теперь стоит задача еще и вернуть какой то результат, вариант со сниппетом отвалился. [code] {$params = [ «modX» => $modx, ]} {processor action=«web/tables/getservicelist» ns=«modxsite» params=$params assign=result} [/code] это вообще корректно? тупо в процессоре импортировать api я не хочу
Выложите листинг процессора getServiceList куда-нибудь. Какой его главный предок? modObjectGetlistPropcessor или что? Если процессор написан по фэншую, что все должно корректно отработаться, там ответ стандартизированный.
блин да ну ладно. неужели так все просто. листинг выкладывать смысла нету ответ получен более чем ожидалось, сразу на несколько вопросов, если вдруг чего тогда уже с листингом приду.
если есть возможность, покажите гист на свой процессор который работает со своей таблицей?
как всегда премного благодарен
Здравствуйте.
Подскажите, как же будет правильно реализовать задачу используя modxSmarty, или может у кого то есть что то похожее то поделитесь как делали.
На сайте все формы взаимодействия с пользователем реализованы в модальных окнах. Существует некая страница modal когда нужно пока показать модальное окно на нее через ajax уходит запрос, сниппет обработчик на основании ключа запроса отдает чанк. Ну и далее ajax возращает сформированное модальное окно. В случае если в модальном окне форма то запрос формы отправлялся на туже страницу modal и вызывался тот же чанк, ключ брался из сессии.
Как сделать такой функционал с использованием modxSmarty, в голову пришла только одна мысль. Сделать нечто похожее на то как устроено подключение шаблонов. Одна страница modal в которой вызывается modal.php (аналог base,php) ну и далее уже по ключу из запроса подсовываем нужный *.tpl модального окна.
Приемлемым ли будет такой механизм? или возможно есть совет по реализации? Спасибо.
можно делать это через обращение к коннектору (как обрабатывается корзина в shopmodxbox) Я по привычке использую другой вариант: создаю документ (например ajax), обязательно некешируемый, и для него создаю шаблон, делаю его статичным и назначаю ему свой php-файл (благодаря расширению templatephp код шаблона может содержать php инструкции) — и там творю что душе угодно. там доступен весь MODX c его вкусностями:
<?php if($_SERVER['HTTP_X_REQUESTED_WITH']=='XMLHttpRequest'){ switch($_REQUEST['action']){ case 'getmenu': $id=(int)$_REQUEST['id']; $r=$modx->getObject('modResource',array('id'=>$id,'template'=>20)); if($r){ $output=$r->get('content'); $maxIterations= intval($modx->getOption('parser_max_iterations', $params, 10)); $modx->parser->processElementTags('', $output, true, false, '[[', ']]', array(), $maxIterations); $modx->parser->processElementTags('', $output, true, true, '[[', ']]', array(), $maxIterations); $ttl=$r->get('longtitle'); if(empty($ttl)) $ttl=$r->get('pagetitle'); return $output; } else{ return 'Ошибка: страница не найдена'; } break; case 'service': $id=(int)$_REQUEST['id']; $r=$modx->getObject('modResource',array('id'=>$id,'template:in'=>array(3,17))); if($r){ $output=$r->get('content'); $maxIterations= intval($modx->getOption('parser_max_iterations', $params, 10)); $modx->parser->processElementTags('', $output, true, false, '[[', ']]', array(), $maxIterations); $modx->parser->processElementTags('', $output, true, true, '[[', ']]', array(), $maxIterations); $ttl=$r->get('longtitle'); if(empty($ttl)) $ttl=$r->get('pagetitle'); $out=json_encode(array('title'=>$ttl, 'content'=>$output, 'alias'=>$r->get('alias'))); return $out; } else{ return json_encode(array('title'=>'Ошибка: страница не найдена', 'content'=>'')); } break; ...
1. При вызове через коннекторы не вызываются MODX-ивенты, и самое главное — OnHandleRequest, а именно на это событие срабатывает плагин, инициализирующий modxSmarty (объект $modx->smarty). То есть если вызывать процессор через коннектор, в процессоре не будет смарти, а вопрос был именно про смарти. При оформлении заказа у нас процессор корзины вызывается на самой странице безаджаксово, поэтому $this->modx->smarty в процессоре доступен. Если через коннектор его вызывать, то не будет объект $this->modx->smarty и выполнение завершится фатальной ошибкой.
Сразу скажу, что если мне нужен смарти в процессоре при вызове через коннектор, я делаю так: в процессоре дописываю код в initialize()
public function initialize(){ if(empty($this->modx->smarty)){ $this->modx->invokeEvent('OnHandleRequest'); } return parent::initialize(); }
2. Старайтесь не использовать этой конструкции if($_SERVER['HTTP_X_REQUESTED_WITH']=='XMLHttpRequest'){… Зачем вам она нужна? Если у вас в логике уже прописано switch($_REQUEST['action']), то это уже фильтрует запросы. Какая разница вам аджаксом запрос отправлен или нет? И, на смарти твой пример надо бы переписать, чтобы по сабжу было :)
3. Под каждый запрос шаблон создавать — не кашерно. Просто документу указывать без шаблона, а в контент прописывать путь до смарти-шаблона [[!smarty?tpl=`......`]]. А в нем уже все прописывать что нужно, и если надо отдать именно в JSON, то преобразовываем данные. Самый простой способ — это вызвать подшаблон, полученные данные в переменную зафигачить и преобразовать данные:
{include $tpl_path assign=result} {json_encode($result)}
Промазал :) Ниже ответил.
чтобы по сабжу было
Это я для примера показал, что все доступно :)
Просто документу указывать без шаблона, а в контент прописывать путь до смарти-шаблона [[!smarty?tpl=`......`]]. А в нем уже все прописывать что нужно
А вот об этом не догадался, учту, спасибо за науку :)
Здравствуйте. Стоит ли использовать процессоры для пустяковых запросов? или можно использовать запрос прям в шаблоне при условии что дальше нам данные абсолютно не нужны Запрос примерно такого характера.
if ($modx->getObject('modResource', $id){ //... }
ИМХО однозначно стоит. Я часто этим пользуюсь и считаю это сильной стороной modxSmarty. Только имейте ввиду, что конструкции типа {$doc->set('pagetitle', $value)} будут возвращать во фронт единичку (ибо успех), поэтому в таких случаях делайте {$ok = $doc->set('pagetitle', $value)}. Тогда результат будет присваиваться переменной и Смарти ничего отправлять в паблик не будет.

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