| |
м следующего блока), а также при
достижении конца файла.
Часть V. Приемы программирования на PHP 450
В случае, если буферизация выходного потока не была включена, функция
возвращает false. Это свойство можно использовать для проверки того, ус-
тановлен ли буфер вывода, или же данные сразу направляются в браузер.
void ob_end_clean()
Вызов данной функции завершает буферизацию выходного потока. При этом все со-
держимое буфера, которое было накоплено с момента последнего вызова
ob_start(), теряется (не попадает в браузер). Конечно, если текст вывода нужен,
необходимо сначала получить его при помощи ob_get_content(). Именно так и
происходит в шаблонизаторе. Вызов функции ob_end_clean() с последующим
ob_start() — единственный способ очистить внутренний буфер PHP.
void ob_end_flush()
Эта функция практически полностью эквивалентна ob_end_clean(), за исключени-
ем того, что данные, накопленные в буфере, немедленно выводятся в браузер
пользо-
вателя. Ее применение оправдано, если мы хотим отправлять данные страницы кли-
енту, параллельно записывая их в переменную для дальнейшей обработки.
Стек буферов
Необходимо сделать несколько замечаний насчет функций "перехвата" выходного
потока программы. Что получится, если больше одного раза подряд вызвать
ob_start()? Хотя об этом не написано ни слова в официальной документации, ри-
скну взять на себя ответственность и заявить, что, в общем-то, ничего
нежелательно-
го не произойдет. Последующие операторы вывода будут работать с тем буфером,
который был установлен самым последним вызовом. При этом функция
ob_end_clean() не завершит буферизацию, а просто установит в активное состоя-
ние "предыдущий" буфер (разумеется, сохранив его предыдущее содержимое). Легче
всего понять этот механизм на примере:
Листинг 30.15. Пример "перехвата" выходного потока
ob_start(); // устанавливаем перехват в буфер 1
echo "1"// попадет в 1-й буфер
ob_start(); // откладываем на время буфер 1 и активизируем второй
echo "2"; // текст попадет в буфер 2
$A[2]=ob_get_contents(); // текст во втором буфере
ob_end_clean(); // отключает буфер 2 и активизируем первый
echo "1"; // попадет опять в буфер 1
$A[1]=ob_get_contents(); // текст в первом буфере
Глава 30. Код и шаблон страницы 451
ob_end_clean(); // т. к. это последний буфер, буферизация отключается
// Распечатываем значения буферов, которые мы сохранили в массиве
foreach($A as $i=>$t) echo "$i: $t ";
// Выводится:
// 2: 2
// 1: 11
?>
Мы видим, что схема буферизации выходного потока чем-то похожа на стек: всегда
используется тот буфер, который был активизирован последним. У такой схемы до-
вольно много положительных черт, но есть и одна отрицательная. А именно, если
какая-то логическая часть программы использует буферизацию выходного потока, но
по случайности "забудет" вызвать ob_end_clean() перед своим завершением, ос-
тавшаяся программа останется "в недоумении", что же произошло. К сожалению, в
PHP мы никак не сможем обойти это ограничение, так что призываю вас быть осо-
бенно внимательными.
Проблемы с отладкой
В последней версии PHP на момент написания этих строк имелось небольшое неудоб-
ство, которое может превратить отладку программ, использующих буферизацию, в
сущий ад. Дело в том, что при включенной буферизации все предупреждения, в нор-
мальном состоянии генерируемые PHP, записываются в буфер, а потому (если про-
грамма не отправляет буфер в браузер) могут потеряться. К счастью, это касается
лишь предупреждений, которые не завершают работу сценария немедленно. Фаталь-
ные ошибки отправляются в браузер почти всегда. Неприятность как раз и состоит
в
этом "почти". Даже фатальные ошибки останутся программистом незамеченными,
если он вызывает функцию ob_start() вложенным образом, — т. е. более одного
раза, как это было описано в предыдущем абзаце. Например, если в листинге 30.15
после присваивания текста элементу массива $A[2] вставить вызов несуществующей
функции, программа сразу же выдаст пользователю текущее содержимое буфера но-
мер 1, а затем, "не сказав ни слова", завершится. Это и понятно: ведь сообщение
об
ошибке попало во второй буфер, а значит, было проигнорировано! Почему разработ-
чики PHP, вопреки общеизвестной практике, не разделили стандартный выходной
поток и поток ошибок, остается неясным.
Если вы заметили, шаблонизатор всегда использует не более одного буфера
"перехва-
та" в каждый мо
|
|