Разработка сайтов, создание сайтов
главная / PHP / Smarty – не просто шаблоны

Smarty – не просто шаблоны

Вступление

Скажем сразу, этот материал не будет вас учить пользоваться базовыми возможностями данной библиотеки. Напротив, я капну гораздо глубже. Цель этого материала взглянуть на шаблонизатор Smarty с другой стороны, и увидеть в нем не просто очень удобный и мощный шаблонный движек, а некий фреймворк для разработки ваших приложений.

Часто, говоря о Smarty, незаслуженно обвиняют его в низкой производительности и «тормознутости», что ж – автор данного материала с указанными товарищами не согласен. Напротив, раз уж мы приняли решение использовать в своем приложении эту библиотеку, я предлагаю вам на полную катушку задействовать ее возможности, отдав на откуп шаблонизатору как вывод информации пользователю, так и управление этой информацией.
Компонентная модель

Одна из сильных сторон Smarty – это возможность создавать свои плагины и расширения. Воспользуемся этой его возможностью в полной мере и попробуем реализовать на ее основе компонентную модель сайта.

Что такое в нашем понимании компонент? Под компонентом я буду подразумевать обособленный блок сайта, который умеет выполнять строго определенный набор действий и, в результате своей работы, либо выводить что-либо на экран, либо готовить какие-то данные для других компонентов.

Компонент – это элемент сайта, который, во-первых, точно знает какие действия он может совершать, во-вторых, какие библиотеки для совершения этих действий ему нужны.

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

В чем положительная сторона такого подхода?
вы пишите специальные классы (объекты) ядра своего сайта, они никак не зависят от вывода на экран, а просто подготавливают и обрабатывают данные, тем самым обеспечивается высокая переносимость кода и возможность его повторного использования;
в случае командной работы, вам не надо заботиться о том, что делает соседний программист, который пишет свой компонент;
стандартизация кода – вы можете создать интерфейс компонента и строго следовать его требованиям, что позволит одному программисту легко разобраться в компоненте другого программиста.

Это основные преимущества данного подхода.
Общие классы

Безусловно, в каждом приложении есть набор классов, которые нужны всем, или большинству компонентов, например, класс для работы с базой. Как поступить в таком случае? И для этой проблемы в Smarty есть удачное решение. Впрочем, давайте по порядку.

Сначала инициализируем класс Smarty:<?php
/** Путь до Smarty */
define ( 'SMARTY_DIR' , '/smarty/' );

/** Путь до Smarty шаблонов */
define ( 'TEMPLATES' , '/templates/' );

/** Путь до Smarty компилированных шаблонов */
define ( 'TEMPLATES_C' , '/templates_c/' );

require_once( SMARTY_DIR . 'Smarty.class.php' );
$smarty = new Smarty;
$smarty -> compile_check = TRUE;
$smarty -> force_compile = TRUE;
$smarty -> template_dir = TEMPLATES;
$smarty -> compile_dir = TEMPLATES_C;
$smarty -> plugins_dir [] = LIBS_PATH;
$smarty -> caching = FALSE;
?>


Итак, Smarty готов к работе. Что необходимо сделать с общими классами, чтобы обеспечить доступ к ним внутри любого компонента?

Скажем, у нас есть несколько общих компонентов:
adodb – класс для работы с базой;
session – класс для работы с сессиями;
errors – класс для обработки ошибок;
variables – класс для хранения и обработки состояния массивов $_GET и $_POST.

Первым делом, нам необходимо создать объекты данных классов (параметры конструкторов зависят от вашей конкретной реализации). В целом, это делается стандартным образом:<?php
require_once( CLASSES_DIR . '/variables.class.php' );
$vars = new Variables ();

require_once( CLASSES_DIR . '/errors.class.php' );
$errors = new Errors ( $smarty );

require_once( CLASSES_DIR . '/security.class.php' );
$security = new Security ( $adodb );

// и так далее...
?>


Объекты созданы и теперь необходимо обеспечить доступ к ним в любом компоненте нашего приложения. Для этого необходимо зарегистрировать данные объекты в Smarty:<?php
$smarty -> register_object ( 'adodb' , $adodb );

$smarty -> register_object ( 'vars' , $vars );

$smarty -> register_object ( 'errors' , $errors );

$smarty -> register_object ( 'security' , $security );
?>


Для регистрации объектов мы используем метод Smartyregister_object(). После чего ваш объект станет доступным везде, где он может понадобиться. Как «достать» нужный вам зарегистрированный объект мы рассмотрим в следующей части.
Функция «Компонент»

К текущему моменту Smarty ничего не знает о каких-либо компонентах, и нам нам надо научить его работать с ними. Для этого мы добавляем к синтаксису шаблонов новый тег – {component}. Чтобы Smarty научился обрабатывать этот тег – пишем простую функцию:<?php
// Smarty function Component
//
// @author Feskov Kuzma

function smarty_function_component ( $params , & $smarty ) {
$adodb = & $smarty -> get_registered_object ( 'adodb' );
$vars = & $smarty -> get_registered_object ( 'vars' );
$errors = & $smarty -> get_registered_object ( 'errors' );
$security = & $smarty -> get_registered_object ( 'security' );

if (empty( $params [ 'name' ])) {
$params [ 'name' ] = 'site_view';
}
if ( is_file ( ADMIN_LIBS_PATH . '/' . $params [ 'name' ] . '.component.php' )) {
require( ADMIN_LIBS_PATH . '/' . $params [ 'name' ] . '.component.php' );
} else {
echo 'Component ' . $params [ 'name' ] . ' not found';
}
unset( $adodb , $errors , $security , $vars );
}
?>


Давайте разберемся, что делает данная функция. Во-первых, она создает обработчик для нового тега – {component}, во-вторых, достает (get_registered_object()) и делает доступными вызванному компоненту зарегистрированные ранее общие объекты.

Немножко теории. Чтобы вызвать данную функцию к жизни, необходимо в любом шаблоне написать тэг {component}. Поскольку функция не выполняет никаких продуктивных действий, и служит исключительно диспетчером компонентов, просто написать {component} недостаточно, поскольку эта команда неинформативна. Конечно, функция не даст сбоя, и запустит принятый по умолчанию компонент 'site_view'. Каким образом уточнить, какой именно компонент вам требуется и как передать ему дополнительные параметры? Все очень просто, мы несколько измени вызов компонента в шаблоне:{component name='имя требуемого компонента' var1='значение параметра' var2='значение другого параметра'}


И так далее, как вы понимаете, name, var1, var2 – это дополнительные параметры для нашего компонента. Name, например, указывает имя компонента, который мы хотим вызвать, а остальные параметры – это дополнительные данные для вызываемого компонента, их количество может быть любым, ровно как и их имена. После того, как в шаблоне встретится указанный выше тег, произойдет вызов нашей функции, которая, в свою очередь, вызовет нужный вам компонент. Все дополнительные параметры будут доступны как в нашей функции так и в вызываемом компоненте, они будут содержаться в массиве $params, где ключ – это название параметра, а значение – соответственно – его значение.

Вступление

Скажем сразу, этот материал не будет вас учить пользоваться базовыми возможностями данной библиотеки. Напротив, я капну гораздо глубже. Цель этого материала взглянуть на шаблонизатор Smarty с другой стороны, и увидеть в нем не просто очень удобный и мощный шаблонный движек, а некий фреймворк для разработки ваших приложений.

Часто, говоря о Smarty, незаслуженно обвиняют его в низкой производительности и «тормознутости», что ж – автор данного материала с указанными товарищами не согласен. Напротив, раз уж мы приняли решение использовать в своем приложении эту библиотеку, я предлагаю вам на полную катушку задействовать ее возможности, отдав на откуп шаблонизатору как вывод информации пользователю, так и управление этой информацией.
Компонентная модель

Одна из сильных сторон Smarty – это возможность создавать свои плагины и расширения. Воспользуемся этой его возможностью в полной мере и попробуем реализовать на ее основе компонентную модель сайта.

Что такое в нашем понимании компонент? Под компонентом я буду подразумевать обособленный блок сайта, который умеет выполнять строго определенный набор действий и, в результате своей работы, либо выводить что-либо на экран, либо готовить какие-то данные для других компонентов.

Компонент – это элемент сайта, который, во-первых, точно знает какие действия он может совершать, во-вторых, какие библиотеки для совершения этих действий ему нужны.

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

В чем положительная сторона такого подхода?
вы пишите специальные классы (объекты) ядра своего сайта, они никак не зависят от вывода на экран, а просто подготавливают и обрабатывают данные, тем самым обеспечивается высокая переносимость кода и возможность его повторного использования;
в случае командной работы, вам не надо заботиться о том, что делает соседний программист, который пишет свой компонент;
стандартизация кода – вы можете создать интерфейс компонента и строго следовать его требованиям, что позволит одному программисту легко разобраться в компоненте другого программиста.

Это основные преимущества данного подхода.
Общие классы

Безусловно, в каждом приложении есть набор классов, которые нужны всем, или большинству компонентов, например, класс для работы с базой. Как поступить в таком случае? И для этой проблемы в Smarty есть удачное решение. Впрочем, давайте по порядку.

Сначала инициализируем класс Smarty:<?php
/** Путь до Smarty */
define ( 'SMARTY_DIR' , '/smarty/' );

/** Путь до Smarty шаблонов */
define ( 'TEMPLATES' , '/templates/' );

/** Путь до Smarty компилированных шаблонов */
define ( 'TEMPLATES_C' , '/templates_c/' );

require_once( SMARTY_DIR . 'Smarty.class.php' );
$smarty = new Smarty;
$smarty -> compile_check = TRUE;
$smarty -> force_compile = TRUE;
$smarty -> template_dir = TEMPLATES;
$smarty -> compile_dir = TEMPLATES_C;
$smarty -> plugins_dir [] = LIBS_PATH;
$smarty -> caching = FALSE;
?>


Итак, Smarty готов к работе. Что необходимо сделать с общими классами, чтобы обеспечить доступ к ним внутри любого компонента?

Скажем, у нас есть несколько общих компонентов:
adodb – класс для работы с базой;
session – класс для работы с сессиями;
errors – класс для обработки ошибок;
variables – класс для хранения и обработки состояния массивов $_GET и $_POST.

Первым делом, нам необходимо создать объекты данных классов (параметры конструкторов зависят от вашей конкретной реализации). В целом, это делается стандартным образом:<?php
require_once( CLASSES_DIR . '/variables.class.php' );
$vars = new Variables ();

require_once( CLASSES_DIR . '/errors.class.php' );
$errors = new Errors ( $smarty );

require_once( CLASSES_DIR . '/security.class.php' );
$security = new Security ( $adodb );

// и так далее...
?>


Объекты созданы и теперь необходимо обеспечить доступ к ним в любом компоненте нашего приложения. Для этого необходимо зарегистрировать данные объекты в Smarty:<?php
$smarty -> register_object ( 'adodb' , $adodb );

$smarty -> register_object ( 'vars' , $vars );

$smarty -> register_object ( 'errors' , $errors );

$smarty -> register_object ( 'security' , $security );
?>


Для регистрации объектов мы используем метод Smartyregister_object(). После чего ваш объект станет доступным везде, где он может понадобиться. Как «достать» нужный вам зарегистрированный объект мы рассмотрим в следующей части.
Функция «Компонент»

К текущему моменту Smarty ничего не знает о каких-либо компонентах, и нам нам надо научить его работать с ними. Для этого мы добавляем к синтаксису шаблонов новый тег – {component}. Чтобы Smarty научился обрабатывать этот тег – пишем простую функцию:<?php
// Smarty function Component
//
// @author Feskov Kuzma

function smarty_function_component ( $params , & $smarty ) {
$adodb = & $smarty -> get_registered_object ( 'adodb' );
$vars = & $smarty -> get_registered_object ( 'vars' );
$errors = & $smarty -> get_registered_object ( 'errors' );
$security = & $smarty -> get_registered_object ( 'security' );

if (empty( $params [ 'name' ])) {
$params [ 'name' ] = 'site_view';
}
if ( is_file ( ADMIN_LIBS_PATH . '/' . $params [ 'name' ] . '.component.php' )) {
require( ADMIN_LIBS_PATH . '/' . $params [ 'name' ] . '.component.php' );
} else {
echo 'Component ' . $params [ 'name' ] . ' not found';
}
unset( $adodb , $errors , $security , $vars );
}
?>


Давайте разберемся, что делает данная функция. Во-первых, она создает обработчик для нового тега – {component}, во-вторых, достает (get_registered_object()) и делает доступными вызванному компоненту зарегистрированные ранее общие объекты.

Немножко теории. Чтобы вызвать данную функцию к жизни, необходимо в любом шаблоне написать тэг {component}. Поскольку функция не выполняет никаких продуктивных действий, и служит исключительно диспетчером компонентов, просто написать {component} недостаточно, поскольку эта команда неинформативна. Конечно, функция не даст сбоя, и запустит принятый по умолчанию компонент 'site_view'. Каким образом уточнить, какой именно компонент вам требуется и как передать ему дополнительные параметры? Все очень просто, мы несколько измени вызов компонента в шаблоне:{component name='имя требуемого компонента' var1='значение параметра' var2='значение другого параметра'}


И так далее, как вы понимаете, name, var1, var2 – это дополнительные параметры для нашего компонента. Name, например, указывает имя компонента, который мы хотим вызвать, а остальные параметры – это дополнительные данные для вызываемого компонента, их количество может быть любым, ровно как и их имена. После того, как в шаблоне встретится указанный выше тег, произойдет вызов нашей функции, которая, в свою очередь, вызовет нужный вам компонент. Все дополнительные параметры будут доступны как в нашей функции так и в вызываемом компоненте, они будут содержаться в массиве $params, где ключ – это название параметра, а значение – соответственно – его значение.

Источник: i-faq.ru
текущее:

НОВОСТИ

2011 г., «VisMech.ru»