О шаблонах
Опубликовано 25 Января, 2013. Рубрики Новости сайта, автор RussianMen
Рано или поздно девелоперу, создающему сайты статусом выше "сайт-визитка", приходится сталкиваться с таким понятием как «шаблоны» или «шаблонизация» визуального представления (не шаблоны проектирования). Что это такое? Механизм шаблонов позволяет отделять визуальное представление веб-приложения (по-скольку работаю только с веб-приложениями, то и рассуждать буду в этом контексте) от бизнес-логики таким образом, чтобы при изменении, например, внутренней логики попутно не приходилось переделывать всю html-верстку. На этом поприще уже давно существует несколько отдельно стоящих флагманских решений, позволяющих создавать довольно гибкие приложения в плане разделения труда дизайнеров-верстальщиков и программистов, а также предотвращать запутанность кода в больших приложениях. Описывать все их нет смысла. Это уже сделано до меня и не один раз. Помимо этого, почти каждая CMS и фрэймворк имеет собственные решения для отделения логики приложения от логики представления.
Конечно, когда речь идет о проекте в десятки тысяч строк кода, когда у заказчика есть возможность нанять и программиста, и верстальщика, то и функционал шаблонов будет только пользой для всех участников проекта. Но когда разработчик в простецкий сайт в 3 страницы начинает втуливать Smarty, это ИМХО уже перебор. В таких случаях я люблю вспоминать выражение Джорджа Шлоснейгела из его замечательной книги "Профессиональное программирование на PHP" – «попытка убить муху молтком».
Действительно, встраивая все тот же Smarty в весьма простой по функционалу сайт, разработчик попросту тратит время. А время, как известно, — деньги. Да и в большинстве случаев заказчику безразлично на каком шаблонизаторе будет работать его сайт. Заказчик больше печется о затраченном времени.
Что же делать, если сайт не "визитка", но и не второй Amazon? Лично я считаю, что в этом случае оптимальное решение проблемы — воспользоваться своей самописной системой шаблонов, весь функционал которой, заточен только для решения узкого круга задач, необходимых для текущего ресурса. Впоследствии вы, возможно, выведите свою "формулу" универсального шаблонизатора с неким минимальным набором функций, расширяемую по мере необходимости в отдельно взятом проекте.
Может показаться, что автор сей статьи весьма скептически относится к Smarty и другим шаблонизаторам. Это не так. Я довольно долго работал с проектом, в котором роль шаблонизатора выполнял все тот же Smarty. И хочу заметить, мне весьма понравилось использование этой системы шаблонов в контексте обширного по функционалу проекта.
Но вернемся к пробелеме разделения визуального от абстракции. Каким минимальным требованиям должен отвечать шаблонизатор в среднем проекте? Возможность назначать переменные шаблону Отдельное пространство имен переменных для отдельно взятого html-шаблона Возможность использования одного шаблона для общего каркаса страницы во избежание повторения конструкций вида require 'header.tpl'; … require 'footer.tpl'; в каждом файле.
К слову, "средний" проект — это некий эталон измерения сложности веб-приложения по моей личной шкале и соотвествует примерно следующим критериям: Проект является интернет-магазином или социальным сообществом 10-20 типов страниц. Подчеркиваю — НЕ страниц, а типов страниц. Например: страница описания товара. Т.е. html-шаблон для этого типа страниц будет один, но самих страниц, когда каталог заполнится контентом будет много.
У каждого девелопера эта шкала своя, так что в этом вопросе прошу строго не судить.
Перейдем от слов к делу.
Рассмотрим простейший класс, который состоит всего из трех методов.
class Template {private $_tmpl;private $_vars = array();public function __construct($filename) {$this->_tmpl = $filename; } public function assign($name, $value) { $this->_vars[$name] = $value; } public function render() { if (count($this->_vars) > 0) { extract($this->_vars); } $tmplPath = "templates/{$this->_tmpl}.tpl"; if (file_exists($tmplPath)) { require $tmplPath; } else { throw new Exception("Шаблон {$this->_tmpl} не найден"); } } }
Давайте рассмотрим пример с применением этого класса. Создадим следующую структуру каталогов:
/wwwroot | — /classes | — Template.php — /templates | — Main.tpl | — Catalog.tpl | — Product.tpl | — Index.tpl | — 404.tpl | — index.php Main.tpl Catalog.tpl
Страница каталога №
Product.tpl
Страница описания продукта №
Index.tpl
Главная страница сайта
404.tpl
Страница не найдена
index.php:
/**
* Буферизация вывода.
*Все, что будет выводиться echo-м или print-ом, будет попадать в буфер, а не в браузер пользователю.
*/
ob_start();
// Подключаем шаблонизатор require dirname(__FILE__).'/classes/Template.php'; //
Производим проверку маршрутизации и включаем необходимые шаблоны //
Если не один из шаблонов не найден, отправляем клиенту код ошибки и показываем шаблон 404.tpl //
Если маршрут не задан, выводим главную страницу if (isset($_GET['route']) && $_GET['route'] == 'catalog') { $tmpl = new Template('Catalog'); $tmpl->assign('ID', $_GET['ID']); $tmpl->render(); } else if ($_GET['route']) && $_GET['route'] == 'product') { $tmpl = new Template('Catalog'); $tmpl->assign('ID', $_GET['ID']); $tmpl->render(); } else if (!isset($_GET['route'])) { $tmpl = new Template('Index'); $tmpl->render(); } else { header("HTTP/1.0 404 Not Found"); $tmpl = new Template('404'); $tmpl->render(); } //
Получаем содержимое буфера $content = ob_get_clean(); //
Инициализируем шаблон каркаса страницы и выводим ранее сгенерированное содержимое $tmpl = new Template('Main'); $tmpl->assign('content', $content); $tmpl->render();
Как видно из примера, содержимое страниц catalog и product изменяется в зависимости от значения $_GET['ID']. Т.о. мы получили два типа шаблонов и неограниченное количество страниц, генерируемых приложением из этих шаблонов.
Вывод: не стремитесь во всех проектах, которыми вы занимаетесь, использовать навороченные библиотеки шаблонизаторов, предоставляющих большое обилие всевозможных инструментов, в большинстве случаев не используемых в должном объеме. Лучше всего написать свое решение, которое поможет сэкономить время, ресурсы, а главное — нервы останутся в порядке.
624
прос