Обычно шаблонизатор Smarty применяется так: вы пишете код, который создаёт набор данных для шаблона, отдаёте вместе с названием шаблона смарти и тот «соединяет бренды», выводя в браузер результат.
Это так называемая модель с ведущими контроллерами. То есть контроллер полностью отвечает за то, что получил шаблонизатор и вообще командует всем.
Ещё есть модель с ведущими представлениями. В ней представление говорит контроллеру «а дай-ка мне, дорогой друг, список последних постов», после чего контроллер дёргает модель, добывает этот список, обрабатывает и отдаёт представлению (в нашем случае — шаблонизатору).
Никакая из этих моделей не является лучшей, в разных случаях удобно использовать то одно, то другое. Тем не менее, смарти-из-коробки умеет работать только по первой схеме. Обучить его работать ещё и по второй оказалось совсем несложно.
Интересное происходит на строках 41-57. Воспользовавшись методом $smarty->register_function() я объявил новую функцию шаблона «data». Когда эта конструкция встречается в шаблоне, происходит вызов метода $this->getDataProxy() объекта SmartyRender.
На вход метода попадает ссылка на массив параметров, заданных в шаблоне и ссылка на объект smarty, который оперирует шаблоном, вызвавшим смарти-функцию.
Как здесь, так и далее нет никакой магии. Мы проверяем параметры и, если с ними всё в порядке, то создаём экземпляр класса DataFetcher. Результат вызова метода fetch() объекта DataFetcher станет переменной шаблона, которую далее можно использовать как угодно.
Сам шаблон в моём случае выглядит вот так:
Работающий код этого примера (включает Smarty): http://gregor.ru/files/blog/vdsmarty.zip
Это так называемая модель с ведущими контроллерами. То есть контроллер полностью отвечает за то, что получил шаблонизатор и вообще командует всем.
Ещё есть модель с ведущими представлениями. В ней представление говорит контроллеру «а дай-ка мне, дорогой друг, список последних постов», после чего контроллер дёргает модель, добывает этот список, обрабатывает и отдаёт представлению (в нашем случае — шаблонизатору).
Никакая из этих моделей не является лучшей, в разных случаях удобно использовать то одно, то другое. Тем не менее, смарти-из-коробки умеет работать только по первой схеме. Обучить его работать ещё и по второй оказалось совсем несложно.
- <?php
- /**
- * index.php
- *
- * View-driven smarty usage sample
- *
- * Use {data id="SOMEID" var="TPLVAR"} construction in template
- * to fetch data for template. Return of the DataFetcher object
- * will be assigned to the variable with TPLVAR name.
- *
- * DataFetcher object must have function called fetch() with only
- * parameter which value will be SOMEID.
- *
- * Smarty included in this archieve only for your convenience.
- *
- * Remember: it's just a sample
- *
- * @copyright (c) Gregory Sitnin, 2009. All rights reserved.
- * @author Gregory Sitnin <gregor@gregor.ru>
- *
- */
-
- $config['base'] = dirname(__FILE__);
- $config['tmp'] = $config['base'].'/tmp';
-
- final class DataFetcher extends ConfiguratedObject {
- function fetch($name) {
- return 'Hello, World!';
- }
- }
-
- final class SmartyRender extends ConfiguratedObject {
- private $smarty;
-
- function __construct($config) {
- parent::__construct($config);
- require_once $this->config['base'].'/smarty/Smarty.class.php';
- $this->smarty = new Smarty();
- $this->smarty->template_dir = $this->config['base'];
- $this->smarty->compile_dir = $this->config['tmp'];
- $this->smarty->register_function('data', array ($this, 'getDataProxy'));
- }
-
- public function getDataProxy($params, &$smarty) {
- if (!isset($params['id'])) {
- $smarty->trigger_error("data: id parameter must be set.");
- } elseif (!isset($params['var'])) {
- $smarty->trigger_error("data: var parameter must be set.");
- } else {
- try {
- $fetcher = new DataFetcher($this->config);
- $smarty->assign($params['var'], $fetcher->fetch($params['id']));
- } catch (Exception $e) {
- $smarty->trigger_error('data: ('.$e->getCode().')'.$e->getMessage());
- }
- }
- }
-
- function render($template, array $vars = null) {
- $this->smarty->assign($vars);
- return $this->smarty->fetch($template);
- }
- }
-
- final class App extends ConfiguratedObject {
- function run() {
- $render = new SmartyRender($this->config);
- echo $render->render('index.tpl');
- }
- }
-
- abstract class ConfiguratedObject {
- protected $config;
-
- function __construct($config) {
- $this->config = $config;
- }
- }
-
- $app = new App($config);
- $app->run();
-
- ?>
* This source code was highlighted with Source Code Highlighter.
Интересное происходит на строках 41-57. Воспользовавшись методом $smarty->register_function() я объявил новую функцию шаблона «data». Когда эта конструкция встречается в шаблоне, происходит вызов метода $this->getDataProxy() объекта SmartyRender.
На вход метода попадает ссылка на массив параметров, заданных в шаблоне и ссылка на объект smarty, который оперирует шаблоном, вызвавшим смарти-функцию.
Как здесь, так и далее нет никакой магии. Мы проверяем параметры и, если с ними всё в порядке, то создаём экземпляр класса DataFetcher. Результат вызова метода fetch() объекта DataFetcher станет переменной шаблона, которую далее можно использовать как угодно.
Сам шаблон в моём случае выглядит вот так:
- <html>
- <head>
- <title>View-driven Smarty test</title>
- </head>
- <body>
- {data id="test" var="test"}
- Fetched: {$test}
- </body>
- </html>
* This source code was highlighted with Source Code Highlighter.
Работающий код этого примера (включает Smarty): http://gregor.ru/files/blog/vdsmarty.zip