Bufor PHP ob_flush () kontra flush ()

79

Jaka jest różnica między ob_flush()i flush()i dlaczego muszę dzwonić do obu?

ob_flush()Referencyjna mówi:

Ta funkcja wyśle ​​zawartość bufora wyjściowego (jeśli istnieje).

flush()Referencyjna mówi:

Opróżnia bufory zapisu PHP i cokolwiek używanego przez PHP zaplecza (CGI, serwer WWW itp.).

Jednak nadal mówi:

[it] może nie być w stanie zastąpić schematu buforowania Twojego serwera WWW…

Więc wydaje mi się, że mógłbym po prostu wykorzystać ob_flush()cały czas. Jednak kiedy to robię, uzyskuję dziwne rezultaty. Czy mógłby ktoś wyjaśnić prostymi słowami, co się tutaj dzieje?

Ben
źródło

Odpowiedzi:

75

ob_flushwysyła bufor inicjowany przez aplikację. W ob_start()każdym skrypcie PHP może być wiele zagnieżdżonych plików. ob_flushprzekazuje bieżącą zawartość do wyższej warstwy.

Sam PHP może (według własnego uznania) buforować dane wyjściowe. To zależy od zaplecza. Ale zwykle FastCGIma własny bufor gniazda. W związku z tymflush() należy również wywołać, aby wysłać bieżącą zawartość na serwer sieciowy.

A teraz serwer WWW może sam zaimplementować inny schemat buforowania ( mod_deflatelub filtr zawartości), na który nie masz wpływu. Ale to rzadko, ponieważ wymaga specjalnej konfiguracji.

W każdym razie użyj obu.

mario
źródło
11
Użyj ob_flush i flush i używaj ich w tej kolejności.
Robino
17
Ważnym szczegółem, którego brakuje w tej odpowiedzi, jest output_bufferingopcja konfiguracyjna, której domyślną wartością w wersjach produkcyjnych php.ini jest 4096. Oznacza to, że po uruchomieniu dowolnego skryptu PHP pierwsze 4096 bajtów danych wyjściowych jest buforowanych (w buforze, który można zrzucić ob_flush()). Dlatego konieczne jest użycie, ob_flush()jak również flush(). Wyłączenie output_bufferingprzez php.ini lub wywołanie ob_end_clean()lub ob_end_flush()na początku skryptu eliminuje tę konieczność.
Mark Amery,
Dzięki @MarkAmery, ale ob_end_clean()na „początku skryptu” wydaje się sprzeczne z intuicją. Masz na myśli, że powinniśmy to uwzględnić wkrótce po ob_start()i przed dwoma rzutami?
Khom Nazid
Cóż, mam ob_start()i ob_end_clean()na samym początku skryptu. Następnie po każdym "echo" w trakcie skryptu dołączam również ob_flush(); flush();i spodziewam się, że podczas gdy skrypt zajmuje trochę czasu, to, co zostało zrobione do tej pory, zostanie wyświetlone na ekranie (w przeglądarce). Ale nic nie wychodzi do samego końca. czego mi brakuje?
Khom Nazid
1
@KhomNazid Obserwacja przeglądarki to nie to samo, co debugowanie strumienia HTTP. Przyrostowe i opóźnione wyjście do niekompletnego HTML DOM prawdopodobnie nie będzie widoczne. Przeprowadź testy CLI z obecną konfiguracją. (A potem, i tylko wtedy, zacznij inne pytanie na ten temat.)
mario
33

ob_flushopróżnia bufory wyjściowe jesteś stworzony z funkcji takich jakob_start

flush opróżnia buforowane wyjście skryptu PHP do jego wywołującego

Dan Grossman
źródło
25

ob_flush()jest spłukiwaniem wysokiego poziomu. Opróżnia bufory wysokiego poziomu i umieszcza całą zawartość w wewnętrznych buforach niskiego poziomu, gotowych do wysłania.

  • Zauważ, że ob_rodzina funkcji tworzy stosy buforów, więc zwykłe pisanie na ślepo ob_flush()wszędzie da ci „dziwne wyniki”, jeśli kod został napisany w celu wykorzystania tego łączenia.

flush() jest opróżnianiem niskiego poziomu, instruującym PHP, aby opróżnił wewnętrzne bufory danych niskiego poziomu.

Poniżej nadal będą bufory warstwy gniazda; poniżej znajdują się bufory warstwy sieciowej. A na najniższym poziomie kolejka elektronów idących w dół kabla danych.

Lekkość wyścigów na orbicie
źródło
Cóż, mam ob_start()i ob_end_clean()na samym początku skryptu. Następnie po każdym "echo" w trakcie skryptu dołączam również ob_flush(); flush();i spodziewam się, że podczas gdy skrypt zajmuje trochę czasu, to, co zostało zrobione do tej pory, zostanie wyświetlone na ekranie (w przeglądarce). Ale nic nie wychodzi do samego końca. czego mi brakuje?
Khom Nazid
@KhomNazid Buforowanie przez etapy pośrednie, takie jak serwer WWW, serwery proxy, twoja przeglądarka ...
Wyścigi Lightness na orbicie
11

Myślę, że jest to związane z twoim poprzednim pytaniem . Istotną zaletą korzystania z buforowania danych wyjściowych jest używanie go razem z kompresją danych. Jeśli nie używasz ob_gzhandler, niewiele możesz zyskać. flushsam po prostu zatwierdzi wszystkie dane wyjściowe, które są nadal na serwerze. Z ob_starti jego odpowiedniki ob_flush, ob_end_cleani ob_end_flush, co czeka na sprężone (spojrzenie flushi ob_flushjako odnoszące się do różnych wiadrach - obwysyła dane flush, flushwysyła dane do przeglądarki - nie mogą być dokładne, ale to pomysł) zostaną opakowane i wysłane do klienta .

bcosca
źródło
Dzięki, analogia do wiadra jest dobrym przykładem.
Ben