php ob start пример

ob_start

Описание

void ob_start ([string output_callback])

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

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

Может быть специфицирована необязательная функция output_callback. Эта функция принимает строку как параметр и должна возвращать строку. Функция будет вызвана при вызове ob_end_flush(), или если буфер выводится в браузер в конце запроса. Когда вызывается output_callback, она примет содержимое буфера вывода как параметр и по идее должна возвратить новый буфер вывода как результат, который будет направлен в браузер.

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

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

ob_end_clean(), ob_end_flush(), ob_clean(), ob_flush() и ob_start() не могут вызываться из callback. Если вы вызовете их из callback-функции, поведение не определено. Если вы хотите удалить содержимое буфера, возвратите «» (нулевую строку) из callback.

Источник

ob_start

Версия: (PHP 4, PHP 5)

Синтаксис:

Параметры:

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

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

ВерсияОписание
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 не сможет быть выполнена.

Описание

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

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

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

Примеры:

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

Источник

ob_start

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

Описание

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

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

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

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

До 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 как сокращение этой комбинации.

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

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

Примеры

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

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

Источник

Все о буферизации вывода в PHP

php ob start пример. Смотреть фото php ob start пример. Смотреть картинку php ob start пример. Картинка про php ob start пример. Фото php ob start пример

Что вы не узнаете из документации, момент с дырой в безопасности + советы о том, как ускорить отклик сервера.

Буферизация вывода позволяет вам сохранять выходные данные PHP (в основном генерируемые echo, var_dump, print_r) в памяти (т.е. в буфере) вместо немедленной передачи в браузер или терминал. Что полезно для самых разных задач:

Предотвращение вывода «на экран»:

Захватить вывод и записать в переменную: (Таким образом можно создавать кэш)

Функции ob_get_contents() и ob_end_clean() могут быть заменены одной функцией: ob_get_clean(), в ее имени больше нет «end» хотя фактически она отключает буферизацию вывода:

В приведенных выше примерах полученный буфер не был отправлен на выход. Если вы хотите отправить его, используйте ob_end_flush() вместо ob_end_clean().

Чтобы получить содержимое буфера, отправить его на выход и отключить буферизацию, есть ещё одна функция (включая отсутствующий end в имени): ob_get_flush().

Буфер так же может быть очищен в любое время не выключая его, используя функцию ob_clean() (очищает буфер) или ob_flush() (отправляет буфер на выход):

В буфер также отправляются выходные данные, записанные в выход php://output, буферизацию можно избежать, записав в php://stdout (или STDOUT), который доступен только в CLI, т.е. при запуске скриптов из командной строки.

Гнездование (вложенные буферы)

Буферы могут быть вложенными, поэтому, когда один буфер активен, другой ob_start() активирует новый буфер. Таким образом, ob_end_flush() и ob_flush() на самом деле отправляют буфер не на выход, а в родительский буфер. И только при отсутствии родительского буфера содержимое отправляется в браузер или терминал.

Поэтому важно отключить буферизацию, даже если происходит исключение:

Размер буфера (chunk_size)

Буферизация также может улучшить производительность сервера, когда PHP не будет отправлять каждое echo в браузер, а вместо этого будет отправлять большие куски данных, например, по 4 кб. Просто вызовите в начале скрипта:

Когда размер буфера превышает 4096 байт, PHP автоматически выполняет flush, т.е. буфер очищается и отправляется. То же самое может быть достигнуто установкой директивы output_buffering, которая игнорируется в CLI.

HTTP заголовки

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

Дыра в безопасности

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

Пользовательские обработчики

Вы можете установить свой собственный обработчик, т.е. функцию, которая будет обрабатывать содержимое буфера перед отправкой:

Этапы start, final и flush (так же clean) могут происходить одновременно. Это можно различить с помощью бинарного оператора &:

Является переводом статьи с phpfashion, здесь очень хорошо описана буферизация в PHP на английском языке. 🙂

Источник

Буфер вывода в PHP

В этой статье я хочу рассказать о том, как реализован слой «буферизации вывода» в PHP, как работает и как с ним взаимодействовать из PHP. В этом слое нет ничего сложного, но многие разработчики либо совсем не понимают, как с ним обращаться, либо не имеют полной ясности. Всё, о чём я буду писать, относится к PHP версии 5.4 и выше. Именно начиная с неё изменились многие вещи, связанные с буфером вывода (БВ). По сути, этот функционал был полностью переписан, поэтому совместимость с версией 5.3 сохранилась лишь частично.

Что такое буфер вывода?

Поток вывода в PHP содержит байты, обычно в виде текста, которые разработчику надо вывести на экран. Чаще всего для этого используется конструкция echo или printf(). Во-первых, нужно понимать, что любая функция, которая что-то выводит, будет использовать БВ из области PHP. Если говорить о расширениях для PHP, то можно получить доступ к функциям, пишущим в SAPI напрямую, в обход любого вышерасположенного БВ. API C задокументировано в lxr.php.net/xref/PHP_5_5/main/php_output.h, отсюда можно почерпнуть немало информации, например, о размере буфера по умолчанию.

Второй важный момент: слой БВ является не единственным слоем, в котором буферизуются выводимые данные.

И третье: в зависимости от SAPI, который вы используете (веб или cli), слой БВ может вести себя по-разному.

Ниже представлена схема, которая поможет понять всё вышесказанное:

php ob start пример. Смотреть фото php ob start пример. Смотреть картинку php ob start пример. Картинка про php ob start пример. Фото php ob start пример

Здесь мы видим, что для управления выводимыми данными в PHP используется три логических слоя буферизации. Два из них принадлежат тому самому «буферу вывода», а третий — SAPI. Когда поток вывода покидает область PHP, чтобы попасть на нижний уровень архитектуры, «по пути» могут возникнуть новые буферы: буфер терминала, буфер FastCGI, буфер веб-сервера, буфер операционной системы, буферы стеков TCP/IP. Не забывайте об этом. Хотя в рамках данной статьи мы будем говорить только о PHP, в стеке на пути данных к нижнему слою и пользователю встретится ещё немало программных средств.

Важное замечание относительно CLI SAPI: он отключает в PHP любой буфер вывода по умолчанию, присвоив в ini параметру output_buffering значение 0. Так что, пока вы в CLI не пропишете вручную функции ob_(), по умолчанию все выводимые данные будут напрямую попадать в слой SAPI. Более того, в CLI для параметра implicit_flush жёстко указано значение 1. Суть этого параметра разработчики вечно понимают неправильно, хотя код говорит совершенно недвусмысленно: когда implicit_flush имеет значение 1, буфер слоя SAPI сбрасывается при каждой записи. То есть каждый раз, когда вы записываете данные для вывода с помощью CLI SAPI, они немедленно отправляются на нижний уровень, где записываются в виде stdout, а потом сбрасываются.

Стандартный PHP-слой буферизации вывода

По умолчанию в php.ini, идущем в составе поставки PHP, output_buffering присвоено значение «4096» (байт). Если вы не используете php.ini (или запускаете PHP с ключом –n), то значением по умолчанию будет «0», то есть отключено. Если захардкодить значение «On», то будет назначен стандартный размер буфера вывода (16 КБ).

Как вы уже, наверное, догадались, использование буфера для вывода в веб-окружении благотворно влияет на производительность. Начальных 4 КБ вполне достаточно, ведь это означает, что вы можете записать до 4096 ASCII-символов, пока PHP не начнёт взаимодействовать с нижерасположенным слоем SAPI. В условиях веба отправка данных побайтно, напротив, производительность не улучшает. Гораздо лучше, если сервер отправляет весь контент скопом или большими частями. Чем реже уровни обмениваются данными, тем лучше с точки зрения производительности. Поэтому обязательно используйте буфер вывода. PHP отправит его содержимое в конце запроса и вам для этого ничего не придётся делать.

В предыдущей главе я упоминал об implicit_flush в контексте CLI. В случае с любым другим SAPI implicit_flush изначально отключён. Это хорошо, поскольку вряд ли вы будете приветствовать сброс SAPI сразу же после записи в него. Для протокола FastCGI сброс можно сравнить с завершением и отправкой пакета после каждой записи. Однако лучше сначала полностью заполнить буфер FastCGI, а уже потом слать пакеты. Если вам нужно вручную сбросить буфер SAPI, используйте для этого PHP-функцию flush(). Для сброса после каждой записи, как уже говорилось выше, можно использовать параметр implicit_flush в php.ini. Как вариант — однократный вызов PHP-функции ob_implicit_flush().

Вы можете использовать только один callback, который получит содержимое буфера и сделает полезные преобразования для вывода, что не может не радовать. Для анализа данных, которые PHP отправляет веб-серверу, а тот отсылает пользователю, полезно использовать callback-и буфера вывода. Кстати, под «выводом» я подразумеваю как заголовок, так и тело. HTTP-заголовки тоже являются частью слоя буферизации вывода.

Тело и заголовки

Когда вы используете буфер вывода (неважно, пользовательский или один из стандартных), то можете отправлять HTTP-заголовки и содержимое как угодно. Любой протокол требует сначала отсылать заголовок, а уже потом тело, но за вас это сделает сам PHP, если вы используете слой БВ. Любая PHP-функция, работающая с заголовками (header(), setcookie(), session_start()), фактически использует внутреннюю функцию sapi_header_op(), которая просто заполняет буфер заголовков. Если после этого записать выводимые данные, например, с помощью printf(), то они запишутся в один из соответствующих буферов вывода. И во время отправки буфера PHP сначала

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

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

Давайте разберём на примерах, как это работает, и что вы можете сделать. Имейте в виду, что если вы хотите использовать стандартный PHP-слой буферизации, то не сможете воспользоваться CLI, поскольку он отключается как слой.

Ниже приведён пример работы со стандартным PHP-слоем с помощью внутреннего веб-сервера SAPI:

Мы запустили PHP со стандартным буфером вывода на 32 байта, после чего сразу же записали в него 31 байт, пока не включилась задержка исполнения. Экран чёрный, пока ничего не отправлено. Затем действие sleep() заканчивается, и мы записываем ещё один байт, тем самым полностью заполняя буфер. После этого он сразу же сбрасывает себя в буфер слоя SAPI, а тот сбрасывает себя в вывод, поскольку implicit_flush имеет значение 1. На экране появляется строка aaaaaaaaaa<31 раз>b, после чего опять начинает действовать sleep(). По его завершении пустой 31-байтный буфер заполняется одним-единственным байтом, после чего PHP завершается и сбрасывает буфер. На экране появляется с.

Так выглядит работа стандартного PHP-буфера без вызова каких-либо ob-функций. Не забудьте, что это именно стандартный буфер, то есть он уже имеется в наличии (только нельзя использовать CLI).

Теперь с помощью ob_start() можно запускать пользовательские буферы, причем столько, сколько нужно, пока память не закончится. Каждый буфер будет помещаться за предыдущим и немедленно сбрасываться в следующий, что постепенно приведёт к переполнению.

Устройство буферизации вывода

Как я уже говорил, начиная с версии 5.4 механизм буферизации вывода был полностью переписан. До этого код был очень неаккуратным, многие вещи сделать было непросто, часто возникали баги. Подробнее об этом можно почитать по ссылке. Новая кодовая база получилась гораздо чище, лучше организована, появились новые возможности. Правда, совместимость с версией 5.3 обеспечивается лишь отчасти.

Пожалуй, одним из самых приятных нововведений стало то, что расширения теперь могут объявлять свои callback-и буфера вывода, конфликтующие с callback-ами других расширений. Ранее было невозможно полностью управлять ситуациями, когда другие расширения тоже могли декларировать свои callback-и.

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

Подводные камни

По большей части они задокументированы, некоторые из них вполне очевидны, а некоторые не слишком. К очевидным можно отнести, например, то, что не следует вызывать какие-либо функции буфера изнутри callback-а БВ, также как и записывать выводимые оттуда данные.

К неочевидным подводным камням можно отнести то, что некоторые функции PHP используют внутренний БВ для самих себя, заполняя его, а затем сбрасывая или возвращая. При этом следующий буфер ставится в стек. К подобным функциям относятся print_r(), highlight_file() и SoapServer::handle(). Не следует использовать их изнутри callback-а БВ – это может привести к непредсказуемым последствиям.

Заключение

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

По умолчанию имеется один буфер вывода, управляемый тремя настройками в ini-файле. Он устроен так, чтобы реже осуществлять операции записи и не слишком часто обращаться к слою SAPI, а значит и к сети. Это сделано для улучшения общей производительности. Также расширения PHP могут декларировать callback-и, запускаемые в каждом буфере — например, для компрессии данных, замены строк, управления HTTP-заголовками и многих других операций.

Источник

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

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