Какая польза от ob_start () в php?

Используется ли ob_start() для output buffering, чтобы заголовки буферизовались и не отправлялись в браузер? Имею ли я здесь смысл? Если нет, то почему мы должны использовать ob_start()?


person Aditya Shukla    schedule 09.12.2010    source источник


Ответы (9)


Думайте о ob_start() как о высказывании: «Начни запоминать все, что обычно выводится, но пока ничего не делай с этим».

Например:

ob_start();
echo("Hello there!"); //would normally get printed to the screen/output to browser
$output = ob_get_contents();
ob_end_clean();

Есть две другие функции, с которыми вы обычно объединяете его: ob_get_contents(), которая в основном дает вам все, что было "сохранено" в буфере с тех пор, как оно было включено с помощью ob_start(), а затем ob_end_clean() или ob_flush(), которая либо останавливает сохранение, либо отбрасывает все, что было сохранено. , или перестает сохранять и выводит все сразу, соответственно.

person Riley Dutton    schedule 09.12.2010
comment
Отличное объяснение. Я бы пошел еще дальше и заменил ob_get_contents() на ob_get_clean() и удалил ob_end_clean(), поскольку ob_get_clean() по сути выполняет обе функции. Ссылка: php.net/manual/en/function.ob-get- clean.php (PHP 4 ›= 4.3.0, PHP 5) - person Con Antonakos; 20.05.2015
comment
Я предполагаю, что для вызова ob_start(); в файле .ini должна быть включена буферизация вывода. Это правильно? Что произойдет, если он не будет включен? - person Kevin Wheeler; 14.08.2015
comment
@Riley Dutton Вы не говорите, почему используется ob_start () - person Vishnu R Nair; 14.10.2015
comment
Была такая же проблема, после исправления моего кода с помощью ob_end_clean он работает как шарм! Спасибо @Riley Dutton - person Martins; 14.01.2016
comment
@Kevin Wheeler Если буферизация вывода не была включена в PHP.ini или .htaccess (что иногда, но не всегда работает), и предыдущий ob_start не выполнялся, то ob_get_contents вернет пустую строку. Выходные данные в конечном итоге могут быть сброшены, где они будут отображаться как выходные данные веб-страницы. - person David Spector; 25.04.2021

Я использую это, чтобы отказаться от PHP с большим количеством HTML, но не отображать его. Это избавляет меня от хранения его в виде строки, которая отключает цветовую кодировку IDE.

<?php
ob_start();
?>
<div>
    <span>text</span>
    <a href="#">link</a>
</div>
<?php
$content = ob_get_clean();
?>

Вместо:

<?php
$content = '<div>
    <span>text</span>
    <a href="#">link</a>
</div>';
?>
person JD Isaacks    schedule 09.12.2010
comment
Можно ли использовать это как способ иметь несколько страниц HTML в одном PHP и вызывать их через GET? - person joshkrz; 29.12.2012
comment
Думаю, да, но это не похоже на хорошую идею. Лучше загружать их из отдельных шаблонов. - person JD Isaacks; 20.01.2013
comment
Обратите внимание, что в этом методе используется ob_get_clean(), а не _ 2_ - person Blazemonger; 25.11.2013
comment
Никогда не задумывался об этом, это невероятно удобный для IDE способ разработки! Кроме того, он избавляет меня от необходимости иметь Javascript или HTML в виде строки в моем PHP, постоянно экранируя \ etc, что раздражает - person J-Dizzle; 05.11.2014
comment
Помог мне! Спасибо @JDIsaacks - person Md. Zubaer Ahammed; 06.11.2016
comment
Ваш наглядный пример дает четкое представление о преимуществах использования ob_start. - person klewis; 03.04.2019

Принятый ответ здесь описывает, что делает ob_start(), а не почему он используется (как был задан вопрос).

Как указано в другом месте, ob_start() создает буфер, в который записывается вывод.

Но никто не упомянул, что в PHP можно складывать несколько буферов. См. ob_get_level ().

Что касается того, почему ....

  1. Отправка HTML в браузер более крупными фрагментами дает выигрыш в производительности за счет снижения нагрузки на сеть.

  2. Передача данных из PHP большими порциями дает преимущество в производительности и емкости за счет уменьшения количества требуемых переключений контекста.

  3. Передача больших блоков данных в mod_gzip / mod_deflate дает преимущество в производительности, поскольку сжатие может быть более эффективным.

  4. буферизация вывода означает, что вы все еще можете манипулировать заголовками HTTP позже в коде

  5. явная очистка буфера после вывода [head] .... [/ head] может позволить браузеру начать маршалинг других ресурсов для страницы до завершения потока HTML.

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

person symcbean    schedule 18.01.2015
comment
Важное примечание: нет необходимости вызывать ob_start () в первый раз на странице, если в PHP.ini включена буферизация вывода, например: output_buffering = 200000. В некоторых случаях, но не во всех, такое включение может быть выполнено в файле .htaccess, например: php_value output_buffering 200000. - person David Spector; 25.04.2021

У вас все наоборот. ob_start не буферизует заголовки, он буферизует содержимое. Использование ob_start позволяет вам хранить контент в серверном буфере до тех пор, пока вы не будете готовы его отобразить.

Это обычно используется для того, чтобы страницы могли отправлять заголовки «после того, как они уже« отправили »некоторый контент (т. Е. Решив перенаправить на полпути во время рендеринга страницы).

person Craige    schedule 09.12.2010
comment
+1 Я тоже был сбит с толку относительно фактического использования функции. Ваш ответ относительно его использования во время перенаправления напомнил мне обо всех случаях, когда у меня уже были отправленные заголовки ошибок. Спасибо - person pat; 02.02.2014

Я предпочитаю:

ob_start();
echo("Hello there!");
$output = ob_get_clean(); //Get current buffer contents and delete current output buffer
person hawx    schedule 13.03.2015
comment
Это правильный способ получить повторяющееся содержимое или содержимое за пределами тегов PHP. Если вам нужен дополнительный вывод, вам понадобится последний вызов ob_start. - person David Spector; 25.04.2021

это необходимо для дальнейшего разъяснения ответа JD Isaaks ...

Проблема, с которой вы часто сталкиваетесь, заключается в том, что вы используете php для вывода html из множества разных источников php, и эти источники часто по какой-либо причине выводятся разными способами.

Иногда у вас есть буквальный HTML-контент, который вы хотите напрямую вывести в браузер; в других случаях вывод создается динамически (на стороне сервера).

Динамический контент всегда (?) Будет строкой. Теперь вам нужно объединить этот строковый динамический html с любым буквальным, прямым отображаемым html ... в одну значимую структуру узлов html.

Обычно это вынуждает разработчика обернуть весь этот прямой для отображения контент в строку (как обсуждал JD Isaak), чтобы его можно было правильно доставить / вставить вместе с динамическим html ... даже если вы на самом деле этого не делаете хочу, чтобы это было завернуто.

Но, используя методы ob _ ##, вы можете избежать этого беспорядка, связанного с переносом строк. Буквальное содержимое вместо этого выводится в буфер. Затем за один простой шаг все содержимое буфера (весь ваш буквальный html) объединяется в вашу строку dynamic-html.

(Мой пример показывает, что буквальный html выводится в буфер, который затем добавляется к html-строке ... посмотрите также пример JD Isaaks, чтобы увидеть string-wrapping-of-html).

<?php // parent.php

//---------------------------------
$lvs_html  = "" ;

$lvs_html .= "<div>html</div>" ;
$lvs_html .= gf_component_assembler__without_ob( ) ;
$lvs_html .= "<div>more html</div>" ;

$lvs_html .= "----<br/>" ;

$lvs_html .= "<div>html</div>" ;
$lvs_html .= gf_component_assembler__with_ob( ) ;
$lvs_html .= "<div>more html</div>" ;

echo $lvs_html ;    
//    02 - component contents
//    html
//    01 - component header
//    03 - component footer
//    more html
//    ----
//    html
//    01 - component header
//    02 - component contents
//    03 - component footer
//    more html 

//---------------------------------
function gf_component_assembler__without_ob( ) 
  { 
    $lvs_html  = "<div>01 - component header</div>" ; // <table ><tr>" ;
    include( "component_contents.php" ) ;
    $lvs_html .= "<div>03 - component footer</div>" ; // </tr></table>" ;

    return $lvs_html ;
  } ;

//---------------------------------
function gf_component_assembler__with_ob( ) 
  { 
    $lvs_html  = "<div>01 - component header</div>" ; // <table ><tr>" ;

        ob_start();
        include( "component_contents.php" ) ;
    $lvs_html .= ob_get_clean();

    $lvs_html .= "<div>03 - component footer</div>" ; // </tr></table>" ;

    return $lvs_html ;
  } ;

//---------------------------------
?>

<!-- component_contents.php -->
  <div>
    02 - component contents
  </div>
person dsdsdsdsd    schedule 09.04.2013

Эта функция предназначена не только для заголовков. С ним можно делать много интересного. Пример: вы можете разбить свою страницу на разделы и использовать ее следующим образом:

$someTemplate->selectSection('header');
echo 'This is the header.';

$someTemplate->selectSection('content');
echo 'This is some content.';

Вы можете записать сгенерированный здесь вывод и добавить его в два совершенно разных места вашего макета.

person jwueller    schedule 09.12.2010
comment
Это похоже на то, что я ищу. Мне нужно рендерить материал в «разделы» (подумайте о файлах JS и CSS), но мне нужно иметь возможность вызывать их в шаблоне (который загружается позже, чем заголовок) ... Итак, если я вызываю $ this- › addcss ('specificCSStoThisView'); Я хочу, чтобы он отображался между тегами ‹head›. Однако я не могу гуглить. Не могли бы вы указать мне правильное направление? Спасибо! - person NoobishPro; 05.12.2015

В существующих ответах не упоминаются следующие вещи: HTTP-заголовок и вложение конфигурации размера буфера.

Конфигурация размера буфера для ob_start:

ob_start(null, 4096); // Once the buffer size exceeds 4096 bytes, PHP automatically executes flush, ie. the buffer is emptied and sent out.

Приведенный выше код улучшает производительность сервера, поскольку PHP будет отправлять большие порции данных, например, 4KB (без вызова ob_start php будет отправлять каждое эхо в браузер).

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

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

ob_start();  // turns on output buffering
$foo->bar();  // all output goes only to buffer
ob_clean();  // delete the contents of the buffer, but remains buffering active
$foo->render(); // output goes to buffer
ob_flush(); // send buffer output
$none = ob_get_contents();  // buffer content is now an empty string
ob_end_clean();  // turn off output buffering

Здесь красиво объяснено: https://phpfashion.com/everything-about-output-buffering-in-php

person sudip    schedule 23.08.2018

Нет, ошибаешься, но направление подходит;)

Буферизация вывода буферизует вывод скрипта. Это (короче) все после echo или print. Дело в том, что заголовки могут быть отправлены только в том случае, если они еще не отправлены. Но HTTP говорит, что заголовки - это самая первая передача. Поэтому, если вы выводите что-то впервые (в запросе), заголовки отправляются, и вы не можете установить другие заголовки.

person KingCrunch    schedule 09.12.2010