Задать вопрос
@Ar123sj

Почему странно работает буферизация в PHP?

Добрый день, заметил одну вещь и не могу понять почему так происходит. Суть вопроса: вывожу по порядку строчки, если выводить как ниже, то всё отлично работает.
<?php

for ($i = 0; $i < 6; $i++) {
	if (ob_get_level()>0) ob_flush(); # очищаю дополнительный буфер
	echo "Строка", $i, "<br>";   # помещаю информацию в текущий буфер
	flush(); # сливаю системный буфер
	sleep(1); 
}
?>

Но если изменить порядок строк, как ниже, первые две строки будут выведены через секунду вместе, хотя вроде бы именно этот порядок правильный : помещаем в дополнительный буфер, сбрасываем из него, сбрасываем из системного буфера. В чём же дело, вариант ниже приведен в учебнике, и он выглядит логично, но работает правильно вариант выше.
<?php

for ($i = 0; $i < 6; $i++) {
	echo "Строка", $i, "<br>";
  if (ob_get_level()>0) ob_flush();
	flush();
	sleep(1);
}
?>
  • Вопрос задан
  • 286 просмотров
Подписаться 2 Простой 15 комментариев
Пригласить эксперта
Ответы на вопрос 2
402d
@402d
начинал с бейсика на УКНЦ в 1988
Давайте разберемся зачем в коде используется буферезация.
Если вы запускаете просто свой скрипт из одного файла без внешних зависимостей, то
вызова ob_start() не было, значит и закрывать нечего.

Почему же так часто мы видим в начале файла (единой точки входа) эту функцию первой ?
1) А чтобы не падали скрипты из-за огрехов программистов: могут попать символы BOM (некоторые редакторы так помечают UTF файлы), затесался перенос строки после закрывающего знака вопроса больше
2) В других случаях это костыли - нужно обработать дополнительно текст, который внешняя либа отправляет в stdout и не умеет возвращать через return.

Поэтому такое извращение и практикуется для авварийных остановов
if (ob_get_level()>0) ob_flush();
Хотя правильнее через while , так как уровней вложенности может быть более одного.

Но главное не надо так писать реальные скрипты! Вы деградируете производительность
апача. Если установлен по дефолту, то 51 клиент увидит мертвый сервер.
Ответ написан
Комментировать
@AUser0
Чем больше знаю, тем лучше понимаю, как мало знаю.
Вы заставляете делать flush() сам PHP. Но из PHP вывод попадает в HTTP-сервер, и вот уже его буфер...

Попробуйте так
echo "Строка{$i}<br><!-- ".str_repeat("#", 500)." -->";
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы