Поясню на примере, заодно узнаете несколько полезных сведений: и как быстро провести эксперимент с какой-либо самописной шаблонизационной функцией, не испортив на время опыта действующие файлы шаблона, и как написать такую функцию, и как применять свои tpl-ки вместо стандартных (что иногда необходимо, когда хотят сделать отличающиеся от основного дизайна landing pages для отдельных товаров или разные виды страничек товара).
Заметка Стоит кратко напомнить список стандартных файлов шаблона, которые обрабатываются соответствующими модулями движка. По умолчанию главной страницей (а более правильно, центральной частью этой страницы) считается файл catalog.tpl. Если мы хотим дополнить главную какой-либо html-разметкой, модулем и тому подобное - изменения нужно делать в этом файле шаблона. Однако не забудьте, что менеджер может задать в настройках сайта (а именно в меню настройки -> Настройки сайта -> Сайт открывать на странице:) иную главную страницу. Тогда эта страница будет обрабатываться другим модулем, следовательно изменения нужно вносить в тот tpl-файл, который связан с этим модулем.
index.tpl - макет страницы сайта без контента центральной части
следующие файлы являются макетами центральной части
account.tpl - личный кабинет покупателя
article.tpl - страница статьи
articles.tpl - список статей
callme.tpl - форма запроса связи "Позвоните мне"
cart.tpl - корзина
catalog.tpl - главная страница (каталог товаров: новинки, хиты, акции и т.п.)
compare.tpl - страница сравнения товаров
feedback.tpl - форма обратной связи
file.tpl - страница медиа файла (документации)
files.tpl - список медиа файлов
fulminant.order.tpl - форма мгновенного заказа товара
login.tpl - форма авторизации на сайте
navigation.htm - пагинация страниц
news.tpl - список новостей
news_item.tpl - страница новости
notifyme.tpl - форма "Уведомить о наличии товара"
order.tpl - страница оформленного заказа
order_success.tpl - страница успешного оформления заказа
page.configurator.tpl - страница оптового заказа
page.quick_cart.tpl - всплывающая плашка "Товар добавлен в корзину"
page.quick_compare.tpl - всплывающая плашка "Товар добавлен в сравнение"
password_remind.tpl - форма "Забыли пароль?"
product.tpl - страница товара
products.tpl - список товаров
registration.tpl - форма регистрации
search.tpl - список найденных товаров
sitemap.tpl - карта сайта
static_page.tpl - страница статической (специальной) страницы
stock.tpl - страница склада
stocks.tpl - список складов
следующие файлы относятся к выдаче информации вне сайта
informer.tpl - информер 1 для внешнего сайта
informerNNN.tpl - информер NNN для внешнего сайта (где NNN - некое число)
price.tpl - макет прайс листа 1
price2.tpl - макет прайс листа 2
price3.tpl - макет прайс листа 3
price4.tpl - макет прайс листа 4
price5.tpl - макет прайс листа 5
price6.tpl - макет прайс листа 6
price7.tpl - макет прайс листа 7
price8.tpl - макет прайс листа 8
следующие файлы являются макетами емейл-писем
email_notifyme_confirm.htm - покупателю о подтверждении подключения к уведомлениям о товарах
email_password_remind.tpl - покупателю о новом пароле
email_coupon_activity.htm - партнеру и админу об активности по скидочным купонам
email_order_payment_to_admin.htm - админу о поступлении оплаты заказа
email_order_payment_to_user.htm - покупателю о принятии оплаты заказа
email_order_to_admin.htm - админу о новом (или изменившемся) заказе
email_order_to_user.htm - покупателю о принятии заказа (или изменениях в нем)
email_post_to_admin.htm - админу о новом комментарии товара/статьи/новости или сообщении обратной связи
email_post_to_user.htm - покупателю о новом комментарии или ответе админа
следующие файлы являются макетами СМС-ок
sms_callme_to_admin.htm - админу о новом запросе "Позвоните мне"
sms_order_change_to_user.htm - покупателю об изменении в заказе
sms_order_payment_to_admin.htm - админу о поступлении оплаты заказа
sms_order_payment_to_user.htm - покупателю о принятии оплаты заказа
sms_order_to_admin.htm - админу о новом заказе
sms_order_to_user.htm - покупателю о принятии заказа
следующий файл является технической заглушкой
missing_template.htm - контент центральной части, когда tpl-файла нет (удален)
Заметка Также напомню, в Impera CMS используется противоходная схема рендеринга страниц. То есть сначала работает основной модуль страницы, по соответствующему ему макету центральной части отрисовывая контент, а затем за дело берется модуль клиентской страницы и вставляет этот контент в макет страницы сайта. В результате файл index.tpl всегда рендерится последним или вообще пропускается, если это был запрос динамической (ajax) подгрузки.
При этом общая схема работы движка, когда браузер клиента запрашивает страницу по некоторому адресу, выглядит так:
- запрос попадает на серверный модуль mod_rewrite
- через корневой .htaccess ЧПУ-адрес транслируется на стартовый скрипт index.php в корне магазина
-
этот скрипт подгружает модуль клиентской страницы - это класс ClientPage
- модуль страницы по транслированному адресу определяет, какой модуль будет основным
-
если такой модуль есть и не выключен менеджером, загружает модуль
- передает управление загруженному основному модулю
- основной модуль делает свои операции
-
далее рендерит связанный с ним tpl-файл
- если такой файл не найден, рендерится файл missing_template.htm
- поддерживается хелпер (файл emulator.php), доступны объявленные в нем функции
- и возвращает получившийся html-контент - всегда через переменную $content
- затем модуль страницы смотрит, есть ли в запросе признак динамической (ajax) подгрузки
-
если признак не замечен, модуль страницы рендерит файл index.tpl, получая полный контент
- если такой файл не найден, рендерится файл missing_template.htm
- поддерживается хелпер (файл emulator.php), доступны объявленные в нем функции
- модуль клиентской страницы отправляет собранный контент в браузер клиента
Готовим опыт Прежде всего создайте в шаблоне тестовый файл http://ваш.сайт/design/ваш_шаблон/html/test.tpl - в нем и будем ставить эксперименты. Теперь выберите какой-нибудь товар на сайте и назначьте ему тестовый шаблон, как показано на скриншоте ниже.
Подобное действие переназначения шаблона в идеале нужно было бы делать сразу с главной страницей, то есть в меню страницы -> Специальные страницы -> [редактировать вашу главную страницу]. Однако в версиях движка <= 140323 отсутствует такая возможность для специальных страниц, и появится только в следующих версиях. Поэтому пока экспериментируем со страницей товара, где эта возможность уже существует.
Готовим хелпер шаблона Поскольку по задаче требуется выполнить непредусмотренные скриптовые действия со стороны движка, а именно прочесть несколько товаров из категории, естественно потребуется каким-то образом получить доступ к исполнению собственных инструкций на уровне PHP.
Для подобных целей движком поддерживается так называемый хелпер шаблона - это обычный php-файл в папке шаблона http://ваш.сайт/design/ваш_шаблон/html/emulator.php, где можем описать свои дополнительные функции, используемые наравне со стандартными функциями в данном шаблоне.
Хелпер должен содержать класс TemplateEmulator и в простейшем виде, когда через некую переменную $BlaBla хотелось бы открыть из шаблона неограниченный доступ ко всем общедоступным методам и объектам движка, мог быть таким:
<?php
class TemplateEmulator {
public function __construct ( & $cms ) {
$cms->smarty->assignByRef('BlaBla', $cms);
}
}
?>
Нужно учесть, хотя этот вариант хелпера открывает массу возможностей по упрощению кода, например сделать прямой запрос к базе данных прямо из tpl-файла, тем не менее с точки зрения безопасности он рушит все ее основы. Ведь в шаблоне открывается бесконтрольное использование любых методов с любым умыслом. Скажем, вот так:
<h1>Пример</h1>
{$BlaBla->db->query('DROP DATABASE Something')}
<p>Ваша база данных Something уничтожена прямо из шаблона!</p>
Поэтому рекомендуется писать хелпер так, чтобы он давал доступ только к тем методам, которые вам нужны. Как правило, этими методами являются самописные дополнительные шаблонизационные функции.
Вот пример хелпера, созданного согласно поставленной задаче - выбрать count случайных товаров из which категории. Для этой цели хелпер предоставляет шаблону функцию getRandomProducts.
Уточнение: Я добавил в хелпер одну отвлеченную функцию - echoHelloWorld и раскрасил цветом ее название в теле хелпера, просто чтобы продемонстрировать, что название в шаблоне и теле хелпера могут в принципе быть как одинаковыми, так и различаться (там это название шаблонизационной функции, здесь это название метода ее обработки). Кроме того, чтобы вдобавок показать, что функция может как что-то возвращать на выход, так и одновременно устанавливать в шаблоне свои переменные, скажем под именем $BlaBla.
<?php
class TemplateEmulator {
// объект движка
protected $cms = null;
// ===================================================================
/**
* Конструктор класса
*
* -------------------------------------------------------------------
*
* @access public
* @param object $cms объект движка
* @return void
*/
// ===================================================================
public function __construct ( & $cms ) {
$this->cms = & $cms;
// регистрируем наши дополнительные функции для шаблона
$this->setSmartyPlugins($cms);
}
// ===================================================================
/**
* Регистрация наших дополнительных функций
*
* -------------------------------------------------------------------
*
* @access protected
* @param object $cms объект движка
* @return void
*/
// ===================================================================
protected function setSmartyPlugins ( & $cms ) {
$cms->smarty->registerPlugin('function', 'getRandomProducts',
array($this, 'getRandomProducts'));
$cms->smarty->registerPlugin('function', 'echoHelloWorld',
array($this, 'handlerHelloWorld'));
}
// ===================================================================
/**
* Обработчик шаблонизационной функции getRandomProducts
*
* -------------------------------------------------------------------
*
* @access public
* @param array $params массив параметров, указанных в вызове:
* count = число извлекаемых товаров
* which = идентификатор категории
* @param object $smarty объект шаблонизатора Smarty
* @return array список товаров
*/
// ===================================================================
public function getRandomProducts ( $params = null, & $smarty = null ) {
// текущий пользователь, если есть
$user = null;
if (isset($this->cms->user)) $user = & $this->cms->user;
// настраиваем фильтр записей
$filter = new stdClass;
// сколько случайных выбрать
$filter->randomcount = isset($params['count']) ? $params['count'] : 3;
// из какой категории
if (!empty($params['which'])) $filter->category_id = $params['which'];
// только разрешенные к показу
$filter->enabled = 1;
// если это обычный посетитель, тогда только не скрытые от неавторизованных
if (empty($user->user_id)) $filter->hidden = 0;
// процент скидки пользователя и его ценовая группа
$filter->discount = isset($user->discount) ? $user->discount : 0;
$filter->price_id = isset($user->price_id) ? $user->price_id : 0;
// исключаем имеющие признак "не для продажи"
$filter->non_usable = -1;
// выбираем товары
$items = null;
$this->cms->db->products->get($items, $filter);
// распаковываем поля записей (некоторые хранятся в упакованном виде)
$this->cms->db->products->unpack_records($items, $filter);
return $items;
}
// ===================================================================
/**
* Обработчик шаблонизационной функции echoHelloWorld
*
// ===================================================================
public function handlerHelloWorld ( $params = null, & $smarty = null ) {
$smarty->assign('BlaBla', 'Какое-то значение');
return '<p>Hello World!</p>';
}
}
?>
Готовим тестовый tpl Скопируйте следующий код в свой тестовый файл test.tpl.
Принцип работы: Вызывается шаблонизационная функция getRandomProducts, которой сообщаем интересующие нас параметры count и which, а результат (список товаров) просим назначить в переменную $listing. Затем выводятся товары этого списка. Далее вызывается шаблонизационная функция echoHelloWorld, которая выведет вместо себя html-фрагмент <p>Hello World!</p> и одновременно назначит содержимое переменной $BlaBla.
<h2>Пример: 5 случайных товаров из категории с идентификатором 12</h2>
{getRandomProducts count=5 which=12 assign=listing}
{if !empty($listing)}
{foreach $listing as $item}
Tовар: {$item->model} <br />
{/foreach}
{/if}
<h2>Пример: 4 случайных товара из текущей категории</h2>
{getRandomProducts count=4 which=$category->category_id assign=listing}
{if !empty($listing)}
{foreach $listing as $item}
Tовар: {$item->model} <br />
{/foreach}
{/if}
{echoHelloWorld}
А здесь уже доступна переменная {$BlaBla}.
После эксперимента, его отладки, останется перенести подходящие вам фрагменты с вызовом шаблонизационной функции getRandomProducts и отрисовкой карточек товаров из тестового tpl-файла в tpl вашей главной страницы, удалить тестовый tpl-файл и вернуть изменение имени шаблона в экспериментальном товаре.