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 та використовуйте їх у такому порядку.
Robino

17
Важливою деталлю, якої не вистачає у цій відповіді, є параметр output_bufferingконфігурації, значення якого за замовчуванням у виробничих версіях php.ini дорівнює 4096. Це означає, що при запуску будь-якого скрипта PHP перші 4096 байти вихідних даних буферизуються (у буфері, що змивається з ob_flush()). Ось чому його потрібно використовувати ob_flush(), а також flush(). Вимкнення output_bufferingчерез php.ini або виклик ob_end_clean()або ob_end_flush()на початку сценарію усуває цю необхідність.
Mark Amery

Дякую @MarkAmery, але ob_end_clean()на "початку сценарію" це здається протиінтуїтивним . Ви маєте на увазі, що ми повинні включити це незабаром після ob_start()і до двох флешів?
Хом Назід,

Ну у мене є 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сам по собі просто фіксує всі вихідні дані, які все ще є на сервері. І, ob_startі його аналоги ob_flush, ob_end_cleanі ob_end_flushвсе, що чекає на стиснення (дивіться flushі ob_flushстосується різних сегментів - obнадсилає дані flush, flushнадсилає дані в браузер - може бути неточним, але це ідея), буде упаковано та відправлено клієнту .


Дякуємо, аналогія відра - це гарний приклад.
Бен,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.