| |
($url)
{ global $BLOCK;
// Собираем все блоки.
_CollectBlocks($url);
// Находим и запускаем главный шаблон. Мы делаем это в последнюю
// очередь, чтобы ему были доступны все блоки, из которых состоит
// страница. Шаблон — обычный блочный файл. В нем обязательно должен
// присутствовать блок Output.
$tmpl=@$BLOCK[BlkTemplate];
if(!$tmpl) {
die("Cannot find the template for $url ".
"(have you defined ".BlkTemplate." block?)");
}
Load($tmpl);
// Возвращаем блок Output.
if(!isSet($BLOCK[BlkOutput])) {
die("No output from template $tmpl ".
"(have you defined ".BlkOutput." block?)");
}
return $BLOCK[BlkOutput];
}
// Эта функция предназначена для внутреннего использования. Она собирает
// блоки из файла, соответствующего указанному $url, в том числе и блоки
// из всех .htaccess-файлов "надкаталогов".
function _CollectBlocks($url)
{ global $BLOCK;
$url=abs_path($url,dirname($GLOBALS["SCRIPT_NAME"]));
// Если путь — не /, то обратиться к "надкаталогу".
if(strlen($url)>1) _CollectBlocks(dirname($url));
// Загрузить блоки самого файла.
Load($url);
}
Часть V. Приемы программирования на PHP 448
// Запускает все фильтры для блока.
function _ProcessContent($name,&$cont,$url)
{ foreach($GLOBALS["BLOCKFILTERS"] as $F)
$F($name,$cont,$url);
}
// "Склеивание" блоков.
// Если тело блока начинается с [name], то оно не просто
// записывается в массив блоков, а "пристыковывается" к значению,
// уже там находящемуся, причем в качестве символа-соединителя
// выступает тело блока с именем name. Если строка name не задана
// (то есть указаны []), используется блок с именем DefaultGlue,
// а если этого блока нет, то соединитель по умолчанию — " | ".
function _FBlkGlue($name,&$cont,$url)
{ global $BLOCK;
if(ereg("^\\[([^]])*]",$cont,$P)) {
$c=substr($cont,strlen($P[0])); // тело блока после [name]
$n=$P[1]; // имя соединителя
// Есть с чем "склеивать"?
if(!empty($BLOCK[$name])) {
$glue=@$BLOCK[$n];
if(!Isset($glue)) $glue=@$BLOCK[BlkDefGlue];
if(!Isset($glue)) $glue=DefGlue;
$cont=$BLOCK[$name].$glue.$c;
}
// "Склеивать" нечего — просто присваиваем.
else $cont=$c;
}
}
// Удаление начальных символов табуляции из тела блока.
// Теперь можно выравнивать HTML-код в документах с помощью табуляции.
// Это оказывается чрезвычайно удобным, если мы используем тэги,
// например, в таком контексте:
// < ?foreach($Book as $k=>$v) {? >
//
// | < ?=$Book['name']? > |
// < ?=$Book['text']? > |
Глава 30. Код и шаблон страницы 449
//
// < ?}? >
function _FBlkTabs($name,&$cont,$url)
{ // используем регулярное выражение в формате PCRE, т. к. это —
// единственный приемлемый способ решения задачи
$cont=preg_replace("/^\t+/m","",$cont);
}
?>
"Перехват" выходного потока
В коде листинга 30.14 есть всего лишь несколько вызовов стандартных функций,
ко-
торые мы еще не рассматривали в этой книге. Я имею в виду функции с префиксами
ob_ (от Output Buffering — Буферизация вывода). Их задача — "перехватить" тот
текст, который выводится операторами echo, а также участками, расположенными
вне PHP-тэгов и ?>, и направить его в строковую переменную для дальнейшей
обработки.
Эти чрезвычайно полезные функции впервые введены в PHP версии 4. Нужно за-
метить, что без них вряд ли можно написать более-менее удобный шаблонизатор.
Я привожу здесь их описания в том виде, который принят в этой книге.
void ob_start()
Вызов данной функции говорит PHP, что необходимо начать "перехват" стандартного
выходного потока программы. Иными словами, весь текст, который выводится опе-
раторами echo или расположен вне участков кода PHP, будет накапливаться в
специ-
альном буфере, а не отправится в браузер. В любой момент времени мы можем полу-
чить все содержимое этого буфера, вызвав функцию ob_get_contents(). В
шаблонизаторе мы вызываем ob_start() каждый раз, когда встречается начало
нового блока.
string ob_get_contents()
Функция возвращает текущее содержимое буфера, который заполняется операторами
вывода при включенном режиме буферизации. Именно ob_get_contents() обеспе-
чивает в нашем шаблонизаторе возможность накопления текста блоков. Она вызыва-
ется (а возвращенные данные записываются в массив) каждый раз, когда заканчива-
ется очередной блок (вернее, перед начал
|
|