Эта статья направлена на то, чтобы выделить подход, который позволяет отделить все от бизнес-логики до логики проектирования, от XHTML от CSS, от Javascript от структуры страницы и т. Д., И в то же время он может быть ленивым и включать, например, информация CSS в том же документе (шаблоне), что и XHTML. Сценарий также может быть использован для более продвинутых функций, связанных с XML, о которых я не буду здесь говорить. Эта статья предполагает некоторое знакомство со Smarty или хотя бы концепцию шаблонов.
Автор: Бретт Замир
Сначала быстрый отказ от ответственности: хотя обсуждение вращается вокруг этого класса расширения Smarty с открытым исходным кодом (называемого SmartyDocB , с документацией ), этот подход может быть применен к шаблонам, основанным на других специфичных для PHP системах шаблонов, в XSL и т. Д. Однако я не У меня не так много времени, чтобы поддерживать код для того, что я опишу ниже (хотя я с радостью постараюсь ответить на вопросы, если смогу), но я чувствую, что сам код является достаточно зрелым, и если ничего другого, то его подход к шаблонам, возможно, уникален, поэтому в случае, если он может быть полезен для других, я обращаю на это ваше внимание. Возможно, если есть интерес, я смогу вернуться к коду позже.
Я начну с нескольких примеров с шаблонами и кратко расскажу о том, как это можно использовать и полезно, затем перейду к особенностям настройки и, наконец, обсудим некоторые будущие цели проекта. В заключение я расскажу об использовании XSL или XQuery для шаблонов и о проблемах переноса шаблонов для использования с другими языками программирования.
Почему и как использовать этот шаблонный подход
Введение в подход HYSOCAMTT «разделяй озабоченность и смешивай их»)
Я не знаю как вы, но когда все предлагают внешние таблицы стилей над тегом <style>, а W3C устарел даже для атрибута @style (который сам по себе включал устаревшие теги HTML, используемые для форматирования), я был несчастный. Не потому, что я не видел мудрости отделять структуру от стиля — но потому, что это означало, что я больше не мог быть ленивым — или фактически чем-то, что часто эквивалентно — я не мог быть таким же эффективным. Я должен был бы на самом деле открыть другой файл, потерять концентрацию (моя кратковременная память плачевна), дублировать работу, найдя некоторые средства ссылки на структурный тег, чтобы можно было применить к нему информацию внешнего стиля, и затем надеяться что, глядя на структурный код в будущем без стилизации подсказок, я смогу узнать по именам своих классов,на какую часть страницы ссылался структурный код.
Например, в то время как в простом HTML старого стиля, чтобы сделать небольшой абзац, я мог бы обойтись с помощью:
<p><small>This website is run by an individual......</small></p>
Для обработки разделения стилей мне нужно:
- Начните с: <p> Этим веб-сайтом управляет человек …… </ p>
- Добавьте класс или идентификатор (для ссылок), чтобы я не делал все свои абзацы небольшими и, в соответствии с хорошей практикой, придумал семантическое, а не стилизованное имя: <p class = «disclaimer»> Этот веб-сайт управляемый человеком … </ p>
- Затем откройте и сохраните новый файл таблицы стилей, учитывая хорошее расположение файла, чтобы перемещение содержимого файла не нарушало связь, а затем добавьте соответствующий <link> (или <? Xml-stylesheet …?> если бы только IE начал поддерживать его) в заголовке моего документа XHTML, чтобы вернуться к таблице стилей.
- Добавьте объявление стиля, включая полное имя свойства (здесь «font-size»), в таблицу стилей: p.disclaimer {font-size: small;}
- Обновите мой XHTML, чтобы убедиться, что он работает.
И затем, в будущем, если я посмотрю на свой шаблон (или файл), я могу забыть, как я стилизовал заявление об отказе от ответственности, и если бы я захотел изменить его, мне пришлось бы открыть файл таблицы стилей, если бы он не был откройте и выполните поиск, чтобы найти это объявление стиля. Или, если бы я смотрел на таблицу стилей, я мог бы не вспомнить все файлы, в которых я использовал отказ от ответственности, поэтому мне пришлось бы открыть все мои файлы, чтобы проверить, будут ли какие-либо предлагаемые изменения стиля в таблице стилей подходит везде.
Опять же, есть много преимуществ разделения стилей, таких как большая доступность, более быстрая загрузка и т. Д., О которых вы можете прочитать во многих других статьях, но вы можете видеть (как вы уже наверняка знаете), насколько громоздким может быть вышеописанное быть (особенно, если вы не любите большинство IDE, как я).
Представьте себе, однако, если вы могли бы сделать следующее в вашем шаблоне:
{moveto target=css}
p.disclaimer {font-size:small;}
{/moveto}
<p class="disclaimer">This website is run by an individual......</p>
И пусть скрипт извлекает содержимое «moveto» в отдельный файл для всего сайта (для всего сайта, потому что это ускоряет загрузку за счет использования преимуществ кэширования, которое происходит, когда браузер встречается с той же таблицей стилей при последующем посещении того же или другая страница сайта, которая включает его). Это именно то, что делает SmartyDocB. Кроме того, он поместит комментарии в файл CSS, которые указывают, из какого шаблона произошел вышеуказанный стиль. Таким образом, если вышеуказанный файл шаблона был назван, footer.tpl, в CSS-файле на стороне сайта (который может включать в себя другой автоматически сгенерированный или отредактированный вручную CSS-контент), то следующий текст будет добавлен вверху файла (вверху чтобы убедиться, что разработчик знал во время тестирования, что последующие (ранее существовавшие) стили не заменяли вновь добавленные:
/* Begin moveto footer.tpl */
p.disclaimer {font-size:small;}
/* footer.tpl end moveto */
Еще более лаконичная опция в SmartyDocB — использовать специальный синтаксис, чтобы избежать дублирования (элемента и имени класса), представленного выше:
<<p eclcss="font-size:small;">>This website is run by an individual......<</p>
Это будет извлекать информацию о стиле, которая будет добавлена во внешний файл CSS (удаляя ее из полученного структурного вывода XHTML), и нацелена в соответствии с текущим элементом (‘e’) и его классом (‘cl’), таким образом «eclcss», тем самым воспроизводя тот же точный эффект, что и выше. Аналогичный атрибут существует для нацеливания на
тег в <head> (полезно для тестирования) или для указания класса псевдоклассом, идентификатором текущего элемента и т. Д.Обратите внимание, что автоматическое написание CSS-файлов, подразумеваемое вышеизложенным, может быть отключено с помощью сценария (безусловно, рекомендуется для живых сайтов, где вы не хотите, чтобы каждый визит на ваш сайт вызывал перезапись CSS-файла!), И при желании может быть доступно (особенно во время отладки) через вызов GET. Например, если запись в файл отключена, вы все равно можете при желании разрешить с помощью сценария добавление чего-то вроде «? Rewrite = 1» (если эта опция включена), чтобы заставить, например, переписать Содержимое {moveto} (в таком случае часть записи CSS-файла не будет иметь места в противном случае, и содержимое {moveto} и любые изменения в нем будут, таким образом, игнорироваться до следующего перезаписи). Перезапись происходит только внутри прокомментированных блоков, поэтому, если вы вручную отредактируете файл,любые части за пределами прокомментированных блоков не должны быть перезаписаны.
Таким образом, у нас есть преимущество в том, что наш результирующий код является красивым и чистым (и позволяет манипулировать стилями всего сайта сразу, если это необходимо), в то время как мы все еще можем быть «грязными», написав наши стили вместе с нашим структурным контентом, или, как я предпочитаю это учитывать, мы все еще можем быть более эффективными и интуитивно понятными, позволяя сдерживать наши стили вместе с теми местами, где мы, скорее всего, будем их ассоциировать. И мы всегда можем взглянуть на полученный файл таблицы стилей, чтобы выяснить, из какого шаблона возник стиль, если мы забыли (или мы можем позже удалить стили из нашего файла шаблона, если мы чувствуем, что они более подходящим образом хранятся в более общем виде). файл шаблона или просто удалите стили из шаблона и из закомментированного блока в таблице стилей). Это также может принести пользу дизайнерам, если они отличаются от нас,так как даже дизайн стиля может быть разделен на части, но при желании может быть повторно собран.
Хотя для обработчиков событий Javascript не существует встроенного эквивалента вышеупомянутого (например, для добавления и загрузки атрибута с содержимым и его преобразования в ненавязчивый Javascript во внешнем файле Javascript), существует способ перетаскивания блока Содержимое Javascript (также с использованием {moveto}, как описано выше для стилей, но установка цели для «code» (подобные псевдонимы используются при нацеливании на внешние файлы, в то время как имена элементов (например, script, style и т. Д.) Используются как цели при отправке заголовку документа)), так же как и методы перестановки DTD, схемы W3C, XSL и даже содержимого личных заметок.
Сценарий также позволяет настроить таргетинг на указанные файлы или заголовок документа и многие другие функции.
Настроить
Настройка SmartyDocB практически идентична настройке Smarty. Единственное отличие состоит в том, что вы должны также включить класс SmartyDocB и определить новый объект на основе этого для SmartyDocB:
require($smarty_dir.'/smarty/libs/Smarty.class.php');
require($smarty_dir.'SmartyDoc2.class.php');
$smarty = new Render_SmartyDoc();
Вы можете добавить функции использования (методы) или переменные (свойства) в ваш объект $ smarty так же, как вы делаете это с Smarty. Например:
$smarty->template_dir ='<path to my templates dir>';
$smarty->compile_dir = '<path to my compile dir>';
$smarty->cache_dir = '<path to my cache dir>';
$smarty->config_dir = '<path to my configs dir>';
Также будут доступны другие методы и свойства, специфичные для SmartyDocB. Я не буду вдаваться в их использование здесь, поскольку их немало (документировано, по большей части в официальной документации , если не в исходном коде). Однако я должен отметить, что после назначения переменных код для отображения документа таким образом, который использует {moveto} и другие специфичные для SmartyDocB функции (например, согласование содержимого XHTML), выглядит следующим образом:
$smarty->displayDoc('mytemplate.tpl');
Обратите внимание, что при использовании displayDoc код вашего шаблона обычно должен использовать специализированные элементы (или полагаться на автоматизированные функции SmartyDocB, например, для автоматического создания тегов <html> и <body>) для создания указанных элементов для верхнего или нижнего колонтитула документ, так как в противном случае сценарий не может определить, где размещать элементы. Например, вы не можете вручную создать тег <style> и тег <head> и т. Д. (Если только вы не используете специализированные элементы, такие как {doc_info style = «…»}, которые можно разместить в любом месте в ваших шаблонах), а затем ожидать, что скрипт найдет созданные вами элементы вручную и вставит автоматически созданные элементы. В идеале в будущем может быть создан скрипт для обнаружения этого, но в настоящее время он этого не делает. Но это не так сложно сделать, и может даже сэкономить вам работу кодирования,поскольку некоторые из них могут быть интеллектуально автоматизированы сценарием.
Будущие цели
Помимо вышеупомянутых идей для автоматического создания ненавязчивого Javascript из встроенных HTML-подобных конструкций и для автоматического обнаружения существующего содержимого заголовка для нацеливания инъекций {moveto}, еще одной важной функцией, которую я надеюсь добавить в будущем, является возможность автоматически обновлять свои шаблоны, если были внесены изменения в целевые блоки файла CSS (или Javascript и т. д.). В настоящее время, если вы вносите изменения в файл CSS в целевых блоках, они могут быть перезаписаны вашим шаблоном, который нацелен на этот блок, если вы посещаете страницу с использованием этого шаблона и у вас не отключена запись файлов, и поскольку нет автоматизированных средств для повторной вставки отредактированного содержимого обратно в шаблон, в настоящее время вам необходимо вручную обновить файл шаблона в таком случае, чтобы отразить изменения.
XSL и Templating
XSL имеет преимущество перед Smarty в том, что он легко допускает будущие преобразования (например, если вы хотите, чтобы ваш шаблонный код позже обновлялся до XHTML 2.0), но я надеюсь, что кто-то может написать эквивалент для синтаксиса Smarty в будущем. Я не использую XSL, хотя он является стандартным и более переносимым между языками (см. Также ниже), поскольку намного проще отличить переменные и функции в фигурных скобках от окружающей разметки, чем использовать даже больше тегов XML (инструкции по обработке немного лучше, особенно если они отображаются в среде IDE, которая может по-разному кодировать их цветом, но они по-прежнему используют угловые скобки, и каждый раз, когда они используются, для ввода требуется дополнительный символ или два !; Функции Smarty не требуют кавычек и т. Д.).
По сути, для адаптации шаблонов XSL к описанному выше подходу потребуется наличие определенных тегов или инструкций по обработке (например, <moveto> или <? Moveto …?>), Которые будут обрабатываться PHP с помощью синтаксического анализатора XML, или, возможно, использование registerPHPFunctions в расширение PHP XSL ).
XQuery и шаблоны
XQuery часто называют забавным языком; он интуитивно понятен и эффективен для тех из нас, кто не мыслит в терминах реляционных таблиц (хотя он также допускает такие вещи, как объединения, объединения и т. д. и даже потенциальное взаимодействие с SQL). К сожалению, на сегодняшний день XQuery доступен для PHP относительно немного: одна частичная, но, к сожалению, несуществующая реализация (в классах PHP XML ) и как часть хорошей (но большой и немного трудновыполнимой). find-shared-hosting-with-support-for) Berkeley DB XML, используемый с расширением PHP DBA .
XQuery обладает потенциалом для использования в качестве шаблонов, и в отличие от XSL, чья рекурсивная природа может вызвать головокружение у процедурного программиста (хотя XQuery, как и в случае с XSL, является декларативным языком), XQuery имеет, по крайней мере, больше «делай то, что делай» Я думаю, что мы, PHP-программисты, можем лучше связать это (помимо того, что они несколько похожи на давний побочный удар PHP, SQL, но подходят для XML и обладают гораздо большей мощностью, чем SQL, особенно для документов с непредсказуемой структурой). -центрические приложения (например, для работы с XHTML, DocBook или TEI)). В контексте шаблона оператор XQuery или серия операторов могут использоваться для рисования из определенных источников (как {include} делает в Smarty, но с определенными частями документа), в то же время опционально окружая его статическим XML.
Помимо возможной замены реляционных баз данных (хотя и реализованных в некоторых реляционных базах данных) в его реализации в собственных базах данных XML, существует даже XQuery в качестве языка на стороне сервера (см., В частности, пример на второй странице статьи, синтаксис которого (используется с Собственная база данных eXist XML) сама по себе напоминает ту, что используется в Smarty). Сам Smarty может даже использовать этот потенциал и определять функции расширения, которые позволяют обрабатывать XQuery таким образом.
Кстати, я создал расширение для Firefox (в бета-версии, поэтому, пожалуйста, отправьте отзыв, если вам это нравится, или напишите мне на brettz9 на сайте yahoo.com) под названием XqUSEme, которое может позволить использовать Saxon-B с открытым исходным кодом. XQuery (или локальная установка Berkeley DB XML), чтобы освоиться с выполнением клиентских XQueries (например, для загруженного в настоящий момент XML-документа на вкладке Firefox или даже для документа, изначально в плохо сформированном HTML, но превращенном в правильно сформированный документ внутреннего представления Firefox в DOM).
Шаблонирование по языкам программирования
Не существует стандарта для шаблонов, который бы работал во всех языках программирования (кроме неловкого, хотя и общепризнанного, мощного XSL). Это прискорбно, я думаю, учитывая, что целью шаблона является создание абстракции, и поскольку он в любом случае отделен от бизнес-логики, я думаю, что было бы неплохо, если бы кто-то захотел переписать программу (например, повернуть веб-сайт PHP в расширение Firefox), чтобы можно было легко переносить код шаблона (и даже иметь стандартный API для взаимодействия с шаблонами на стороне бизнес-логики). Тем не менее, я думаю, что есть средства вокруг этого, как упомянуто ниже.
Несмотря на то, что победители PHP могут предпочесть сравнить PHP с Java, я склонен сравнивать его с Javascript — оба потому, что они оба являются языками программирования для масс, они весьма полезны, если не являются необходимыми в дизайне веб-сайтов, они оба с открытым исходным кодом, и они к счастью оба слабо типизированных языка. (К счастью, потому что это, по крайней мере, снижает барьер для входа, но также способствует быстрой разработке приложений, и я думаю, что большая ясность в коде объясняется отсутствием повсеместной типизации, позволяющей сосредоточиться на логике; однако я не буду здесь можно продолжить бесконечные и бесконечные дебаты. Они могут даже превзойти свою специализацию (например, PHP GTK для использования на стороне клиента или Javascript на стороне сервера, как в расширении Firefox POW).
Поскольку они часто сочетаются друг с другом и могут изучаться одними и теми же людьми, я думаю, что существует большой потенциал для того, чтобы те, кто знаком с одним языком, могли еще легче выучить другой, в том числе с использованием систем шаблонов. * Один класс I думаю, что созрела такая адаптация — шаблоны Javascript от Trimpath . Я считаю, что это может быть адаптировано к синтаксису Smarty, чтобы разработчикам PHP было проще использовать свои знания Smarty при разработке приложений Javascript (таких как Firefox). **
Я надеюсь, что эта статья может быть интересна и полезна.
Бретт Замир
* Хотя может показаться заманчивым, что Javascript (по крайней мере, «Ненавязчивый Javascript», который регистрирует обработчики событий, внешние по отношению к его X / HTML) неизбежно отделен от структуры, поскольку в идеале он находится в своем собственном файле, но все еще существуют общие средства, например, при использовании DOM, который создает контент и который может — особенно в больших приложениях, таких как те, которые используются при создании расширений Firefox — вместо этого хотеть включить вместе со статическим содержимым в один и тот же шаблон (ы). (Механизм шаблонов Javascript, такой как Trimpath, по-прежнему полагается на DOM, но в остальном избавляет разработчика от необходимости указывать свой собственный контент, смешанный с функциями DOM.)
** В том же духе я мог бы упомянуть, что мы создали вики Javascript , чтобы позволить нам создавать библиотеки кода, которые могут реализовывать функции PHP в Javascript и наоборот (конечно, могут быть некоторые несоответствия, но Я полагаю, что это могло бы значительно помочь загрузке памяти иметь эквивалентные функции, особенно интуитивные и обильные функции PHP, доступные на другом языке). Я предполагаю, что JsLib уже применил этот подход в некоторой степени, но я хотел бы видеть, что он реализован универсально и максимально близко к реальным функциям PHP. Есть еще волонтеры?
Вы можете связаться с автором на brettz9 на сайте yahoo.com с дальнейшими вопросами или предложениями о работе!
Первоначально опубликовано на Zend’s DevZone . Используется с разрешения.