Буфер PHP ob_flush () против flush ()

79

В чем разница между ob_flush()и flush()и почему я должен звонить обоим?

В ob_flush()ссылке говорится:

Эта функция отправит содержимое выходного буфера (если есть).

В flush()ссылке говорится:

Очищает буферы записи PHP и любой серверной части PHP (CGI, веб-сервер и т. Д.).

Однако он продолжает говорить:

[он] не сможет изменить схему буферизации вашего веб-сервера ...

Так что мне кажется, что я мог бы использовать ob_flush()все время. Однако при этом я получаю странные результаты. Может ли кто-нибудь простыми словами объяснить, что здесь происходит?

Бен
источник

Ответы:

75

ob_flushотправляет инициированный приложением буфер. В ob_start()любом сценарии PHP может быть несколько вложенных . ob_flushпередает текущее содержимое на верхний уровень.

Сам PHP может (по своему усмотрению) буферизовать вывод. Это зависит от серверной части. Но обычно FastCGIимеет собственный буфер сокета. Следовательно, его также flush()необходимо вызвать для отправки текущего содержимого на веб-сервер.

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

В любом случае используйте оба.

Марио
источник
11
Используйте ob_flush и flush и используйте их в указанном порядке.
Робино
17
Важная деталь, отсутствующая в этом ответе, - это output_bufferingпараметр конфигурации, значение которого по умолчанию в производственных версиях php.ini равно 4096. Это означает, что при запуске любого PHP-скрипта первые 4096 байт вывода буферизуются (в буфере, который можно очистить ob_flush()). Вот почему необходимо использовать ob_flush()также flush(). Отключение output_bufferingчерез php.ini, вызов ob_end_clean()или ob_end_flush()запуск скрипта устраняет эту необходимость.
Марк Эмери
Спасибо @MarkAmery, но ob_end_clean()в "начале скрипта" кажется нелогичным . Вы имеете в виду, что мы должны включить это сразу после ob_start()и до двух промывок?
Хом Назид 07
Ну, у меня есть ob_start()и ob_end_clean()в самом начале сценария. Затем, после любого «эха» во время сценария, я также включаю ob_flush(); flush();и ожидаю, что пока сценарий требует времени, все, что было сделано до сих пор, будет выводиться на экран (в браузере). Но ничего не выложено до самого конца. Что мне не хватает?
Хом Назид
1
@KhomNazid Наблюдение браузера - это не то же самое, что отладка потока HTTP. Добавочный и отложенный вывод в неполную HTML DOM вряд ли будет виден. Проведите некоторое тестирование CLI с вашей текущей настройкой. (И тогда, и только тогда, начните другой вопрос об этом.)
Марио
33

ob_flushочищает выходные буферы , созданные с помощью такой функции, какob_start

flush сбрасывает буферизованный вывод самого скрипта PHP вызывающей стороне

Дэн Гроссман
источник
25

ob_flush()это флеш высокого уровня. Он очищает буферы высокого уровня и помещает весь контент во внутренние буферы низкого уровня, готовые к отправке.

  • Обратите внимание, что ob_семейство функций создает стеки буферов, поэтому простая слепая запись ob_flush()повсюду действительно даст вам «странные результаты», если код был написан для использования этого стекирования.

flush() это низкоуровневый сброс, инструктирующий PHP очистить внутренние низкоуровневые буферы данных.

Ниже этого уровня будут буферы уровня сокетов; ниже находятся буферы сетевого уровня. И, на самом низком уровне, очередь электронов, идущих по кабелю данных.

Гонки легкости на орбите
источник
Ну, у меня есть ob_start()и ob_end_clean()в самом начале сценария. Затем, после любого «эха» во время сценария, я также включаю ob_flush(); flush();и ожидаю, что пока сценарий требует времени, все, что было сделано до сих пор, будет выводиться на экран (в браузере). Но ничего не выложено до самого конца. Что мне не хватает?
Хом Назид
@KhomNazid Буферизация промежуточными этапами, такими как веб-сервер, прокси, ваш браузер ...
Гонки
11

Я думаю, это связано с вашим предыдущим вопросом . Существенным преимуществом использования буферизации вывода является то, что она используется вместе со сжатием данных. Если вы не употребляете ob_gzhandler, ничего не добьетесь. flushв одиночку просто зафиксирует все выходные данные, которые все еще находятся на сервере. With ob_startи его аналоги ob_flush, ob_end_cleanи ob_end_flushвсе, что ожидает сжатия (посмотрите flushи ob_flushкак относится к разным корзинам - obотправляет данные flush, flushотправляет данные в браузер - может быть неточным, но это идея) будет упаковано и отправлено клиенту .

Bcosca
источник
Спасибо, аналогия с ведром - хороший пример.
Бен