Функция PHP ob_start(): всё, что нужно знать
Функция ob_start() включает буферизацию вывода в PHP, позволяя захватывать, изменять и управлять выводом скрипта до его отправки клиенту.
Когда PHP выполняет скрипт, каждый вызов echo, print или блок HTML обычно сразу же отправляется клиенту. Буферизация вывода меняет это поведение: она удерживает всё, что скрипт должен вывести, в буфере в памяти, чтобы вы могли захватить, изменить или отбросить данные до того, как они покинут сервер. Функция ob_start() — это встроенная функция, которая включает такую буферизацию.
В этой главе объясняется, что делает ob_start(), её параметры, как захватывать и преобразовывать вывод, наиболее распространённые реальные сценарии использования и типичные ошибки.
Что такое функция ob_start()?
ob_start() включает буферизацию вывода. Пока буферизация активна, ничто из того, что выводит скрипт, не отправляется в браузер. Вместо этого данные накапливаются во внутреннем буфере до тех пор, пока вы явно не отправите их (flush), не получите в виде строки или не очистите.
Буферизация не задерживает HTTP-заголовки. Поскольку тело ответа больше не отправляется сразу, вы всё ещё можете вызывать такие функции, как header(), после того как уже выводили данные через echo — это единственная наиболее распространённая причина, по которой разработчики прибегают к ob_start().
Буферы также вкладываются: каждый вызов ob_start() добавляет новый буфер в стек, а соответствующая функция закрытия/сброса извлекает верхний. Вы можете узнать глубину стека с помощью ob_get_level().
Синтаксис
ob_start(
?callable $callback = null,
int $chunk_size = 0,
int $flags = PHP_OUTPUT_HANDLER_STDFLAGS
): boolПараметры:
$callback— Необязательный. Функция, которая получает содержимое буфера (и битовую маску состояния) и возвращает строку для фактического вывода. Используйте её для преобразования всего, что выводит скрипт, — например, для минификации HTML или его gzip-сжатия.$chunk_size— Необязательный. Если больше0, обратный вызов выполняется каждый раз, когда буфер достигает указанного размера в байтах, а не только при сбросе буфера.0(по умолчанию) означает сброс только при завершении.$flags— Необязательный. Битовая маска, определяющая, можно ли очищать, сбрасывать и удалять буфер. Значение по умолчаниюPHP_OUTPUT_HANDLER_STDFLAGSразрешает все три операции.
Возвращаемое значение: true при успехе, false при неудаче.
Базовое использование: захват вывода
Наиболее распространённый паттерн — начать буфер, вывести что-нибудь, затем захватить это в переменную с помощью ob_get_clean() (которая за один шаг возвращает буфер и отключает буферизацию):
<?php
ob_start(); // start buffering — nothing is sent yet
echo "Hello, ";
echo "world!";
$output = ob_get_clean(); // grab the buffer as a string, stop buffering
echo strtoupper($output); // now we control what actually gets sentВывод:
HELLO, WORLD!Здесь два вызова echo никогда не достигают клиента напрямую. ob_get_clean() возвращает "Hello, world!", и в итоге выводится только версия в верхнем регистре. Этот поток «захват — преобразование» и делает буферизацию мощным инструментом.
Преобразование вывода с помощью обратного вызова
Вместо ручного захвата вы можете передать обратный вызов в ob_start(). PHP автоматически запустит его над буфером при его сбросе (здесь — в конце скрипта):
<?php
function addBang(string $buffer): string
{
return str_replace("world", "World!", $buffer);
}
ob_start("addBang");
echo "hello world";
// buffer is flushed automatically at script end → callback runsВывод:
hello World!Именно так работают встроенные обработчики, например ob_gzhandler() — передайте его в качестве обратного вызова, и вся страница будет прозрачно сжата gzip.
Распространённые сценарии использования
- Отправка заголовков после вывода. Поскольку тело ответа буферизуется, вы всё ещё можете вызывать
header()илиsetcookie()после вывода HTML, избегая ошибки «headers already sent». См.headers_sent(). - Шаблонизация. Захватывайте отрендеренный HTML файла шаблона в строку вместо его прямого вывода, чтобы его можно было вернуть, кешировать или обернуть в макет.
- Постобработка всей страницы. Минифицируйте HTML, переписывайте URL или удаляйте комментарии через обратный вызов перед отправкой.
- Сжатие. Используйте
ob_gzhandlerдля сжатия ответов без изменения вызововechoв скрипте.
Связанные функции
ob_start() редко используется в одиночку. Эти функции управляют созданным ею буфером:
ob_get_contents()— Возвращает содержимое буфера без его очистки.ob_get_clean()— Возвращает буфер и отключает буферизацию.ob_clean()— Отбрасывает содержимое буфера, но оставляет буферизацию включённой.ob_end_flush()— Отправляет буфер клиенту и отключает буферизацию.ob_end_clean()— Отбрасывает буфер и отключает буферизацию (ничего не отправляет).ob_get_level()— Возвращает количество текущих вложенных буферов.
Более широкий обзор см. в разделе PHP Output Control.
Типичные ошибки
- Всегда закрывайте то, что открыли. Каждый
ob_start()должен быть сопоставлен с вызовом flush/clean. Незакрытый буфер автоматически сбрасывается в конце скрипта, но незакрытые буферы в длинных скриптах могут скрывать вывод или тратить память. ob_get_clean()возвращаетfalse, если буфер не активен. Вызов без соответствующегоob_start()даётfalse, а не пустую строку.- Буферизация ≠ бесконечные заголовки. Сами заголовки не буферизуются; буферизуется только тело. Как только любой буфер сброшен клиенту, заголовки зафиксированы.
Заключение
ob_start() включает буферизацию вывода, чтобы PHP удерживал вывод скрипта в памяти вместо немедленной отправки. Это позволяет захватывать вывод в строку, преобразовывать его с помощью обратного вызова, отправлять заголовки после вывода или сжимать всю страницу. Используйте её вместе с ob_get_clean() для захвата, ob_end_flush() для отправки и ob_end_clean() для отбрасывания — и помните, что нужно всегда закрывать каждый открытый буфер.