1. Главная страница » Компьютеры » Ob start php примеры

Ob start php примеры

Автор: | 16.12.2019

Продолжаю публиковать статьи из серии «PHP для начинающих», в этот раз речь пойдёт о буфере вывода.

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

Для начала, даю установку — буферов вывода в PHP несколько, плюс ещё модули web-сервера могут выполнять буферизацию, да ещё и браузеры могут играться с выводом и не сразу отображать полученный результат (надо бы тут освежить память, а то за упоминание Netscape могут освежевать).

Вот теперь буду рассказывать о буферизации в PHP.

Пользовательский буфер вывода

Работа с буфером вывода начинается с функции ob_start() — у данной функции есть три опциональных параметра, но о них я расскажу чуть позже, а пока запоминаем — для включения буфера вывода используем функцию ob_start() :

Если же нам надо сохранить данные, или ещё как обработать вывод то нам потребуется функция ob_get_contents() . Сохранив данные, можно очистить и отключить буфер — для этого воспользуемся функцией ob_end_clean() , если свести всё перечисленное до кучи, то в результате получим следующий код:

Практически все нужные нам функции имеют префикс «ob_», как не трудно догадаться это сокращение от «output buffer»

Функцию ob_get_contents() можно вызывать множество раз, на практике с таким не сталкивался:

Если вы стартанули буфер вывода, но по какой-то причине не закрыли его, то PHP это сделает за вас и в конце работы скрипта выполнит «сброс» буфера вывода в браузер пользователя

Если внутри блока ob_start – ob_end вы отправляете заголовок, то он не попадает в буфер, а сразу будет отправлен в браузер:

В результате выполнения данного кода в http-пакете появятся следующие заголовки:

Естественно, данный код больше ничего не выводит, будет пустая страница.

Данное правило по отправке заголовков верно как для непосредственного вызова функции header() , так и для неявного при вызове session_start() :

Перед вами небольшой life-hack – в PHP вы можете использовать скобочки <> для выделения некой логики в блоки, при этом никакой функциональной нагрузки они не несут, а вот читаемость кода – повышают

Чуть-чуть прояснили ситуацию — теперь в копилке наших знаний есть информация о том, как включить буфер, как получить из него данные, и как выключить. Что ещё интересное можно с ним вытворять? Да с ним практически ничего толком и не сделать — его можно отправить (сбросить) в браузер (ключевое слово flush), очистить (clean), отключить (end). Ну и скомбинировать это всё до кучи тоже можно:

  • ob_clean() — читаем название функции как «очищаем буфер вывода»
  • ob_flush() — «отправляем буфер вывода»
  • ob_end_clean() — «буфер вывода отключаем и очищаем»
  • ob_end_flush() — «буфер вывода отключаем и отправляем в браузер»
  • ob_get_clean() — «получаем буфер вывода, очищаем и отключаем» — тут небольшой отступление от правила, эта функция должна именоваться как ob_get_end_clean() , но решили упростить, и выкинули end
  • ob_get_flush() — «отправляем буфер вывода, очищаем и отключаем», ob_get_ end _flush()

Что можно из перечисленного делать с буфером вывода, определяется третьим опциональным параметром $flags при вызове функции ob_start() , используется крайне редко

Для простого запоминания вот вам наглядная табличка по данному семейству функций:

вернёт очистит отправит отключит
ob_get_contents X
ob_clean X
ob_flush X
ob_end_clean X X
ob_end_flush X X
ob_get_clean X X X
ob_get_flush X X X

Задание
Дополните приведенный ниже код вызовом одной функции, чтобы он корректно вывел «hello world»:

Обработчик буфера

Пора вернуться к функции ob_start() и её первому параметру — $output_callback — обработчик буфера вывода. В качестве обработчика буфера должна быть указана callback-функция, которая принимает содержимое буфера как входной параметр и должна вернуть строку после обработки:

В данном примере функция обработчик вернёт строку «Length of string ‘hello world’ is 11».

Важный момент — с этими функциями нужно быть поосторожней, обработали строки и ладненько, но не пытайтесь вывести либо сохранить данные, не пытайтесь стартовать другой буфер вывода внутри функции, и да есть функции которые создают буфер вывода внутри себя, вот print_r() и highlight_file() тому пример

Из стандартных же обработчиков можете повстречать ob_gzhandler(), но лучше сжатие страничек оставлять на плечах web-сервера, и не вешать это на PHP.

Ещё момент, второй параметр $phase callback-функции может включать в себя флаги из семейства PHP_OUTPUT_HANDLER_* , но вам эта информация никогда не понадобится, я даже пример не смог придумать, зачем оно надо.

We need to go deeper©

У буфера вывода есть килер-фича – внутри буфера можно стартовать ещё один буфер, а внутри нового ещё и так далее (пока памяти хватает):

Читайте также:  Lpt порт на материнской плате

В данном примере функция ob_flush() и производные от неё, будут «выбрасывать» содержимое буфера на более высокий уровень.

Данный подход поможет в случае, когда вам нужно подключить сторонний код, а он вдруг может что-то взять и вывести — было бы разумно обернуть его вывод в буфер, даже если весь ваш код уже обёрнут в другой буфер.

Если вы не знаете точно на какой «глубине» находитесь – то воспользуйтесь функцией ob_get_level(), а чтобы «проснуться» вам пригодится следующий код:

Задание
Внесите изменения в код с вложенными вызовами ob_start() таким образом, чтобы цифры выводились в обратном порядке, для этого надо переставить три строчки кода.

Буфер «по умолчанию»

Если захотите создать обёртку над всем кодом, то для этого можно воспользоваться решением «из коробки» — буфер вывода «по умолчанию», за активацию оного отвечает директива output_buffering, её можно выставить как в On , так и указать размер буфера который нам потребуется (при достижении лимита, буфер будет отправлен в браузер пользователю). Данная директива должна быть проставлена либо в php.ini, либо в .htaccess (для апача), попытка выставить данное значение с использование ini_set() ни к чему не приведёт, т.к. PHP уже стартанул, и буфер вывода уже сконфигурирован согласно настроек:

Если при включенном буфере проверить уровень вложенности и вызвать функцию ob_get_level() , то получим 1:

Т.е. если включить данный буфер, то можно будет избежать ошибок вида «headers already sent»? Да, пока буфера хватит, но никогда так не делайте, ведь понадеявшись на данный метод, вы фактически заложите бомбу замедленного действия, и неизвестно когда она «рванёт» и посыпит ошибками:

Запомните, для CLI приложений директива output_buffering всегда 0, т.е. данный буфер отключен

Зачем это всё?

Хороший вопрос — зачем нужна работа с буфером вывода? Приведу несколько основных сценариев использования:

  1. Сжатие передаваемых данных — с использованием уже упомянутой ob_gzhandler()
  2. Отложенный вывод, чтобы избежать ошибки «headers already sent» (о данной ошибке подробно рассказано в статье Сессия)
  3. Работа с чужим кодом, который пытается самостоятельно что-то выводить
  4. Работа с HTML файлами: когда вам надо подключать текстовый файл (обычно речь о HTML), для дальнейшей работы с его содержимым

Сценарий обработки ошибок в подключаемых файлах — стартуете буфер, подключаете файлы, если что-то пошло не так, то содержимое буфера можно скинуть, и вместо неинформативного сообщения об ошибке, выводите не менее информативное сообщение, что сервер приболел, и не может больше ничего.
Пример работы с критическими ошибками вы можете найти в статье Обработка ошибок, и там тоже упоминается буфер вывода, ох видать всё это ж-ж-ж неспроста

Системный буфер вывода

С пользовательским буфером вывода разобрались, давайте теперь к системному перейдём — это такой буфер вывода, который наполняется по ходу выполнения скрипта, и отправляется в браузер по окончанию выполнения. Т.е. данный буфер вывода есть всегда, его не нужно создавать, но мы можем им управлять.

Вот так всё просто и кратко, ну а теперь о нюансах управления системным буфером вывода…

Royal flush

10 секунд вашего внимания…

А теперь из академического интереса давайте рассмотрим реализацию данного «экшена» – там совсем чуть-чуть кода, и небольшая горстка полезных знаний по PHP:

Сразу бросается в глаза вызов функции flush() — вызвав данную функцию вы даёте указание PHP «сбросить» системный буфер, т.е. отправить всё что там есть в браузер пользователю (но учтите, если у вас стартован пользовательский буфер, то для начала надо будет «сбросить» его, и уже потом вызвать flush() ). Т.е. происходящее можно описать как:

Ещё одна особенность, о которой нужно помнить — директива implicit_flush, отвечает за то, чтобы после каждого вывода автоматически вызывался flush() , поэтому следующая комбинация сработает аналогично предыдущему примеру:

Данную директиву можно изменять «на лету», для этого достаточно вызвать функцию ob_implicit_flush() (удивительное рядом, данную функцию стоило всё же назвать implicit_flush() , т.к. к пользовательскому буферу вывода она имеет опосредственное отношение — после вызова ob_flush() будет вызван flush() ):

Данные примеры работают только при выключенном output_buffering , иначе вам нужно будет его принудительно выключить и очистить в самом скрипте. Если же вы работаете в CLI, то знайте implicit_flush всегда включён, а output_buffering выключен, следовательно весь вывод будет без промедления попадать в консоль

Задание

Для выполнения данного задания вам потребуется освежить знания по подключению файлов

Для закрепления изученного материала, вам нужно реализовать простейший шаблонизатор, который оживит следующий код:

Читайте также:  Intel xeon e5450 сравнение

Рекомендованная литература

  • Хардкорно про буфер вывода в статье PHP output buffer in deep (перевод Буфер вывода в PHP)
  • Ссылка на официальное руководство по настройка php.ini
  • Статья Streaming and Output Buffering

В заключение

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

(PHP 4, PHP 5, PHP 7)

ob_start — Включение буферизации вывода

Описание

Эта функция включает буферизацию вывода. Если буферизация вывода активна, вывод скрипта не высылается (кроме заголовков), а сохраняется во внутреннем буфере.

Содержимое этого внутреннего буфера может быть скопировано в строковую переменную, используя ob_get_contents() . Для вывода содержимого внутреннего буфера следует использовать ob_end_flush() . В качестве альтернативы можно использовать ob_end_clean() для уничтожения содержимого буфера.

Некоторые web-сервера (например Apache) изменяют рабочую директорию скрипта, когда вызывается callback-функция. Вы можете вернуть ее назад, используя chdir(dirname($_SERVER[‘SCRIPT_FILENAME’])) в callback-функции.

Буферы вывода помещаются в стек, то есть допускается вызов ob_start() после вызова другой активной ob_start() . При этом необходимо вызывать ob_end_flush() соответствующее количество раз. Если активны несколько callback-функций, вывод последовательно фильтруется для каждой из них в порядке вложения.

Список параметров

Можно задать необязательный параметр output_callback . Эта функция принимает строку в виде аргумента и должна также вернуть строку. Она вызывается при сбросе (отправке) или очистке (с помощью ob_flush() , ob_clean() или подобных функций) или если буфер вывода сбрасывается в браузер по окончанию запроса. При вызове функции output_callback , она получает содержимое буфера и должна вернуть обновленное содержимое для буфера вывода, который будет отправлен браузеру. Если output_callback не является допустимой функцией, то документируемая функция вернет FALSE . Описание функции для этого параметра:

Если output_callback вернет FALSE , то оригинальная информация отправится в браузер без изменений.

Параметр output_callback может быть игнорирован передачей значения NULL .

ob_end_clean() , ob_end_flush() , ob_clean() , ob_flush() и ob_start() не могут вызываться из callback-функций, так как их поведение непредсказуемо. Если вы хотите удалить содержимое буфера, то верните "" (пустую строку) из callback-функции. Вы так же не можете вызывать функции print_r($expression, true) или highlight_file($filename, true) из callback-функций буферизации вывода.

В PHP 4.0.4 функция ob_gzhandler() была введена для облегчения отправки gz-кодированных данных web-браузерам, поддерживающим сжатые web-страницы. ob_gzhandler() определяет тип кодировки содержимого, принимаемый браузером, и возвращает вывод соответствующим образом.

Если передан не обязательный параметр chunk_size , то буфер буден сброшен после любого вывода превышающего или равного по размеру chunk_size . Значение по умолчанию означает, что функция вывода будет вызвана, когда буфер будет закрыт.

До PHP 5.4.0, значение 1 было специальным значением, которое устанавливало параметр chunk_size в 4096.

Параметр flags является битовой маской, которая управляет операциями, которые можно совершать над буфером вывода. По умолчанию она позволяет буферу вывода быть очищенным, сброшенным и удаленным, что равносильно значению PHP_OUTPUT_HANDLER_CLEANABLE | PHP_OUTPUT_HANDLER_FLUSHABLE | PHP_OUTPUT_HANDLER_REMOVABLE , или PHP_OUTPUT_HANDLER_STDFLAGS как сокращение этой комбинации.

Each flag controls access to a set of functions, as described below:

Константа Функции
PHP_OUTPUT_HANDLER_CLEANABLE ob_clean() , ob_end_clean() , и ob_get_clean() .
PHP_OUTPUT_HANDLER_FLUSHABLE ob_end_flush() , ob_flush() , и ob_get_flush() .
PHP_OUTPUT_HANDLER_REMOVABLE ob_end_clean() , ob_end_flush() , и ob_get_flush() .

Возвращаемые значения

Возвращает TRUE в случае успешного завершения или FALSE в случае возникновения ошибки.

Список изменений

Версия Описание
7.0.0 В случае, если ob_start() используется внутри callback-функции буфера вывода, эта функция больше не будет приводить к ошибке E_ERROR , а вместо этого будет вызывать E_RECOVERABLE_ERROR , позволяя сторонним обработчикам ошибок поймать ее.
5.4.0 Третий параметр ob_start() изменен с булева ( boolean ) параметра erase (который при установке в FALSE предотвращал удаление буфера до тех пор, пока не завершалась работа скрипта) на целочисленный ( integer ) параметр flags . К сожалению, это означает появление несовместимости API для кода, который использовал третий параметр до версии PHP 5.4.0. Смотрите пример с флагами, чтобы понять как работать с кодом, чтобы он поддерживал совместимость с обеими версиями.
5.4.0 Параметр chunk_size, установленный в 1, теперь приводит к выводу по 1 байту в выходной буфер.
4.3.2 Функция вернет FALSE в случае, если output_callback не сможет быть выполнена.
Читайте также:  Iusb3xhc sys синий экран как исправить

Примеры

Пример #1 Пример callback-функции, определенной пользователем

function callback ( $buffer )
<
// заменить все яблоки апельсинами
return ( str_replace ( "яблоки" , "апельсины" , $buffer ));
>

Это все равно что сравнить яблоки и апельсины.

(PHP 4, PHP 5, PHP 7)

ob_start — Включение буферизации вывода

Описание

Эта функция включает буферизацию вывода. Если буферизация вывода активна, никакой вывод скрипта не отправляется (кроме заголовков), а сохраняется во внутреннем буфере.

Содержимое этого внутреннего буфера может быть скопировано в строковую переменную, используя ob_get_contents() . Для вывода содержимого внутреннего буфера следует использовать ob_end_flush() . В качестве альтернативы можно использовать ob_end_clean() для очистки содержимого буфера.

Некоторые веб-серверы (например, Apache) изменяют рабочую директорию скрипта при вызове callback-функции. Вы можете вернуть ее назад, используя chdir(dirname($_SERVER[‘SCRIPT_FILENAME’])) в callback-функции.

Буферы вывода помещаются в стек, то есть допускается вызов ob_start() после вызова другой активной ob_start() . При этом необходимо вызывать ob_end_flush() соответствующее количество раз. Если активны несколько callback-функций, вывод последовательно фильтруется для каждой из них в порядке вложения.

Список параметров

Можно задать необязательный параметр output_callback . Эта функция принимает строку в виде аргумента и должна также вернуть строку. Она вызывается при сбросе (отправке) или очистке (с помощью ob_flush() , ob_clean() или подобных функций) или если буфер вывода сбрасывается в браузер по окончанию запроса. При вызове функции output_callback , она получает содержимое буфера и, как ожидается, должна вернуть обновленное содержимое для буфера вывода, которое будет отправлено браузеру. Если output_callback не является допустимой функцией, то эта функция вернет FALSE . Описание функции для этого параметра:

Если output_callback вернет FALSE , то оригинальная информация отправится в браузер без изменений.

Параметр output_callback может быть игнорирован передачей значения NULL .

ob_end_clean() , ob_end_flush() , ob_clean() , ob_flush() и ob_start() не могут вызываться из callback-функций, так как их поведение непредсказуемо. Если вы хотите удалить содержимое буфера, то верните "" (пустую строку) из callback-функции. Вы также не можете использовать функции буферизации вывода, такие как print_r($expression, true) или highlight_file($filename, true) из callback-функции.

Функция ob_gzhandler() была введена для облегчения отправки gz-кодированных данных браузерам, поддерживающим сжатые веб-страницы. ob_gzhandler() определяет тип кодировки содержимого, принимаемый браузером, и возвращает вывод соответствующим образом.

Если передан необязательный параметр chunk_size , то буфер буден сброшен после любого вывода, превышающего или равного по размеру chunk_size . Значение по умолчанию означает, что функция вывода будет вызвана, когда буфер будет закрыт.

До PHP 5.4.0, значение 1 было специальным значением, которое устанавливало параметр chunk_size в 4096.

Параметр flags является битовой маской, которая управляет операциями, которые можно совершать над буфером вывода. По умолчанию она позволяет буферу вывода быть очищенным, сброшенным и удаленным, что равносильно значению PHP_OUTPUT_HANDLER_CLEANABLE | PHP_OUTPUT_HANDLER_FLUSHABLE | PHP_OUTPUT_HANDLER_REMOVABLE или PHP_OUTPUT_HANDLER_STDFLAGS как сокращение этой комбинации.

Каждый флаг управляет доступом к набору функций, как описано ниже:

Константа Функции
PHP_OUTPUT_HANDLER_CLEANABLE ob_clean() , ob_end_clean() и ob_get_clean() .
PHP_OUTPUT_HANDLER_FLUSHABLE ob_end_flush() , ob_flush() и ob_get_flush() .
PHP_OUTPUT_HANDLER_REMOVABLE ob_end_clean() , ob_end_flush() и ob_get_flush() .

Возвращаемые значения

Возвращает TRUE в случае успешного завершения или FALSE в случае возникновения ошибки.

Список изменений

Версия Описание
7.0.0 В случае, если ob_start() используется внутри callback-функции буфера вывода, эта функция больше не будет приводить к ошибке E_ERROR , а вместо этого будет вызывать E_RECOVERABLE_ERROR , позволяя сторонним обработчикам ошибок поймать ее.
5.4.0 Третий параметр ob_start() изменен с логического ( boolean ) параметра erase (который при установке в FALSE предотвращал удаление буфера до тех пор, пока не завершалась работа скрипта) на целочисленный ( integer ) параметр flags . К сожалению, это означает появление несовместимости API для кода, который использовал третий параметр до версии PHP 5.4.0. Смотрите пример с флагами, чтобы понять как работать с кодом, чтобы он поддерживал совместимость с обеими версиями.
5.4.0 Параметр chunk_size, установленный в 1, теперь приводит к выводу по 1 байту в выходной буфер.

Примеры

Пример #1 Пример callback-функции, определенной пользователем

function callback ( $buffer )
<
// заменить все яблоки апельсинами
return ( str_replace ( "яблоки" , "апельсины" , $buffer ));
>

Это все равно что сравнить яблоки и апельсины.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *