Анимация
JavaScript


Главная  Библионтека 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 [ 145 ] 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189

Примечание

Наверное, вы уже заметили, что блочный файл, который обрабатывается шаб-лонизатором, представляет собой ни что иное, как код на PHP с вызовами управляющих функций типа Block(). Этим мы достигаем множества преимуществ, самое главное из которых - значительное ускорение работы шаблонизатора по сравнению со способом "ручного" разбора файлов. Кроме того, отладочные качества сценария при таком подходе ничего не теряют: файлы блоков загружаются с помощью include, а значит, случись там ошибка, PHP исправно покажет имя файла и номер строки, где это произошло. Правда, остается единственный недостаток: несколько некрасивый синтаксис определения блоков, естественный лишь для программиста, но не для дизайнера. Что же, всегда приходится идти на какие-то жертвы

Внимательно взгляните на определение блока Template. Как уже упоминалось, этот блок содержит имя шаблона, который будет задействоваться при отображении страницы. То, что блоки из родительских каталогов наследуются файлами, позволяет нам задать Template в одном-единственном месте, автоматически распространив его действие на все файлы в каталоге. Не правда ли, это как раз то, чего мы так долго добивались?

Шаблонизатор также обрабатывает специальным образом еще один блок. Его название - Output. Тело именно этого блока выводится в браузер пользователя, когда вся страница уже обработана. Обычно блок Output вставляют только в шаблон страницы, потому что использование его в любом другом месте оказывается бессмысленным (все равно он переопределится в шаблоне).

Автоматическая генерация названий

Если пользователь находится на сайте "Книжный магазин" в разделе "Философия" на заинтересовавшей его странице "Современность", то, конечно, в заголовке окна браузера ему бы хотелось видеть что-то вроде "Книжный магазин Философия Современность", а не просто "Современность". Мы уже договорились хранить название страницы в блоке Title. Но, конечно, мы бы не хотели записывать в каждой странице название полностью, потому что:

□ в будущем мы можем перенести страницу в другой раздел;

□ мы, возможно, захотим сменить разделитель на /;

□ это нарушает концепцию минимальной избыточности данных, что, как мы уже неоднократно убеждались, не приводит ни к чему хорошему.

Обратите внимание на то, что в приведенном файле конфигурации задаются также и некоторые директивы Apache, которые заставляют сервер запускать программу шаблонизатора каждый раз, когда пользователь обращается к HTML-документу. Мы уже знакомы с этими директивами: в главе 29 они использовались для того, чтобы обеспечить подключение библиотекаря к каждому сценарию сервера.



Специально для решения такого рода задач в нашем шаблонизаторе предусмотрим механизм, который я далее буду называть автоматической склейкой тел блоков. Вот как он работает. Если при обработке очередного блока шаблонизатор видит, что его тело начинается с подстроки [Клей], он определяет, что текст должен быть "пристыкован" к предыдущему телу одноименного блока, но не должен заменить его. В качестве "строки-клея" выступает значение блока с именем Клей. Это позволяет нам в будущем изменить символ "склейки" лишь в одном месте, чтобы это затронуло весь сайт. В случае, если указана пустая пара квадратных скобок [] (то есть имя блока было опущено), используется тело блока с именем DefaultGlue (см. листинг 30.12), а если и он отсутствует - то .

Теперь при загрузке страницы /phil/index.html из листинга 30.11, пользователь увидит ее полное название, составленное из блоков Title всех "надкаталогов" и самого файла страницы. Мы добиваемся этого, определив блок Title следующим образом:

<?Block("Title","[]Философия")?>

Поддержка механизма поиска включаемых файлов

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

С помощью данной функции мы можем разбивать сложные шаблоны на части. Например, так можно было бы поступить с блоком, занимающимся формированием карты текущего раздела, особенно если существует несколько шаблонов, отображающих эту карту. Функцию Load() можно вызывать в любом месте страницы или даже из файла .htaccess. Блоки, генерируемые ей, будут вставлены непосредственно перед тем блоком, в котором она была вызвана.

На примере использования библиотекаря мы уже убедились, насколько утомительным может быть указание абсолютных путей к файлам. Поэтому функция Load() умеет сама искать включаемые файлы по серверу. Она делает это всякий раз, когда ей задан относительный путь к файлу. Поиск ведется на основе списка так называемых каталогов для поиска шаблонизатора. Этот список можно пополнять с помощью вызова Inc(), как это сделано, например, в листинге 30.12. Функция Inc() довольно интеллектуальна: даже если ей передан относительный путь к каталогу, она переводит его в абсолютный. Так что при использовании Load() из файла, расположенного в другом каталоге, не происходит никаких недоразумений.



( Замечание

С загрузкой интерфейсов посредством Uses() все обстоит несколько сложнее. Вполне может возникнуть ситуация, когда один и тот же интерфейс требуется в разных местах шаблона страницы для выполнения различных действий. Функ-

Фильтры блоков

После того, как тело блока вычислено, шаблонизатор производит его дополнительную обработку. Делается это с помощью специальных функций-фильтров. Например, " склеивание" названий осуществляется именно таким фильтром. Система устроена таким образом, что позволяет добавлять и удалять фильтры прямо в процессе работы. Для этого программисту достаточно лишь написать код функции-фильтра, а затем добавить имя этой функции в специальную таблицу фильтров (см. исходный код шаблонизатора).

В той версии шаблонизатора, которую мы сейчас рассматриваем, имеется и еще один " стандартный" фильтр. Его задача - удалить из тел блоков все начальные символы табуляции, сколько бы их ни было. Это позволяет программистам и дизайнерам свободно делать отступы в HTML-коде документов, не думая о том, что символы табуляции будут увидены пользователем при просмотре кода страницы. Впрочем, возможно, это и излишество (в конце концов, кому какое дело, как выглядит исходный код страницы).

Примечание

Ради интереса вы можете написать фильтр, который превращает все символы перевода строки в пробелы. Таким образом, исходный код страницы, которую получит пользователь, будет представлять собой одну длинную строку. Код этого фильтра занимает буквально одну строку на PHP!

Поддержка трехуровневой схемы разработки сценариев

Несомненно, наш шаблонизатор будет поддерживать трехуровневую схему разработки сценариев. Иначе и быть не могло: мы не должны удалять из системы то, что прекрасно работает. Наверное, вы уже заметили, что в телах блоков мы можем свободно применять операторы PHP, а это требование является главным для любой схемы.

Чтобы не "засорять" каталоги сайта сценариями - интерфейсами и генераторами данных - предлагается разместить все, что не относится к HTML-файлам и блокам, в отдельном (недоступном извне) каталоге. Им может быть, например, тот самый каталог, где располагаются различные модули. Ведь что такое ядро сценария, как не обычная библиотека, предоставляющая функции для всеобщего использования?! Взятие на вооружение такой техники также снимает с нас заботу об указании полного пути к файлам ядра, поскольку они находятся в общедоступном каталоге модулей, а значит, могут быть включены при помощи Uses().



0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 [ 145 ] 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189