PHP-Puffer ob_flush () vs. flush ()

79

Was ist der Unterschied zwischen ob_flush()und flush()und warum muss ich beide anrufen?

Die ob_flush()Referenz sagt:

Diese Funktion sendet den Inhalt des Ausgabepuffers (falls vorhanden).

Die flush()Referenz sagt:

Leert die Schreibpuffer von PHP und dem von PHP verwendeten Backend (CGI, Webserver usw.).

Es heißt jedoch weiterhin:

[it] kann das Pufferungsschema Ihres Webservers möglicherweise nicht überschreiben.

Also, scheint mir, dass ich die ob_flush()ganze Zeit nutzen könnte. Allerdings bekomme ich dabei seltsame Ergebnisse. Könnte jemand in einfachen Worten erklären, was hier los ist?

Ben
quelle

Antworten:

75

ob_flushsendet einen von der Anwendung initiierten Puffer. ob_start()In jedem PHP-Skript können mehrere verschachtelte Dateien vorhanden sein. ob_flushÜbergibt den aktuellen Inhalt an die obere Ebene.

PHP selbst kann (nach eigenem Ermessen) die Ausgabe puffern. Dies hängt vom Backend ab. Hat aber normalerweise FastCGIeinen eigenen Socket-Puffer. Daher flush()muss auch aufgerufen werden, um den aktuellen Inhalt an den Webserver zu senden.

Und jetzt implementiert der Webserver möglicherweise selbst ein anderes Pufferschema ( mod_deflateoder einen Inhaltsfilter), auf das Sie keinen Einfluss haben. Dies ist jedoch selten der Fall, da es speziell konfiguriert werden muss.

Verwenden Sie auf jeden Fall beide.

Mario
quelle
11
Verwenden Sie ob_flush und flush und verwenden Sie sie in dieser Reihenfolge.
Robino
17
Das wichtige Detail, das in dieser Antwort fehlt, ist die output_bufferingKonfigurationsoption, deren Standardwert in Produktionsversionen von php.ini 4096 ist. Das bedeutet, dass beim Starten eines PHP-Skripts die ersten 4096 Bytes der Ausgabe gepuffert werden (in einem Puffer, der mit gespült werden kann ob_flush()). Aus diesem Grunde ist es notwendig ist , zu verwenden , ob_flush()sowie flush(). Durch Deaktivieren output_bufferingüber php.ini oder Aufrufen ob_end_clean()oder ob_end_flush()zu Beginn des Skripts wird diese Notwendigkeit beseitigt.
Mark Amery
Danke @MarkAmery, aber ob_end_clean()am "Anfang des Skripts" scheint dies nicht intuitiv zu sein. Sie meinen, wir sollten dies bald nach ob_start()und vor den beiden Spülungen einbeziehen?
Khom Nazid
Nun, ich habe ein ob_start()und ein ganz ob_end_clean()am Anfang des Skripts. Nach jedem "Echo" während des Skripts füge ich auch hinzu ob_flush(); flush();, und ich gehe davon aus, dass während das Skript Zeit benötigt, alles, was bisher getan wurde, auf dem Bildschirm (im Browser) ausgegeben wird. Aber bis zum Ende wird nichts ausgegeben. Was vermisse ich?
Khom Nazid
1
@KhomNazid Eine Browser-Beobachtung ist nicht dasselbe wie das Debuggen des HTTP-Streams. Eine inkrementelle und verzögerte Ausgabe in ein unvollständiges HTML-DOM ist wahrscheinlich nicht sichtbar. Führen Sie einige CLI-Tests mit Ihrem aktuellen Setup durch. (Und dann und nur dann, beginnen Sie eine andere Frage darüber.)
Mario
33

ob_flushLeert die von Ihnen erstellten Ausgabepuffer mit einer Funktion wieob_start

flush Leert die gepufferte Ausgabe des PHP-Skripts selbst an seinen Aufrufer

Dan Grossman
quelle
25

ob_flush()ist eine High-Level-Spülung. Es löscht Puffer auf hoher Ebene und legt den gesamten Inhalt in den internen Puffern auf niedriger Ebene ab, die zum Senden bereit sind.

  • Beachten Sie, dass die ob_Funktionsfamilie Stapel von Puffern erstellt. ob_flush()Wenn Sie also überall blind schreiben , erhalten Sie in der Tat "seltsame Ergebnisse", wenn der Code geschrieben wurde, um diese Stapelung zu nutzen.

flush() ist ein Low-Level-Flush, der PHP anweist, seine internen Low-Level-Datenpuffer zu leeren.

Darunter befinden sich noch Socket-Layer-Puffer. Darunter befinden sich Puffer auf Netzwerkebene. Und auf der untersten Ebene die Warteschlange der Elektronen, die das Datenkabel hinunterlaufen.

Leichtigkeitsrennen im Orbit
quelle
Nun, ich habe ein ob_start()und ein ganz ob_end_clean()am Anfang des Skripts. Nach jedem "Echo" während des Skripts füge ich auch hinzu ob_flush(); flush();, und ich gehe davon aus, dass während das Skript Zeit benötigt, alles, was bisher getan wurde, auf dem Bildschirm (im Browser) ausgegeben wird. Aber bis zum Ende wird nichts ausgegeben. Was vermisse ich?
Khom Nazid
@ KhomNazid Pufferung durch Zwischenstufen, wie den Webserver, Proxies, Ihren Browser ...
Helligkeitsrennen im Orbit
11

Ich denke, das hängt mit Ihrer vorherigen Frage zusammen . Der wesentliche Vorteil der Verwendung der Ausgabepufferung besteht darin, dass sie neben der Datenkomprimierung verwendet wird. Wenn Sie nicht verwenden ob_gzhandler, gibt es wenig zu gewinnen. flushAllein werden nur die noch auf dem Server befindlichen Ausgabedaten festgeschrieben. Mit ob_startund seine Kollegen ob_flush, ob_end_cleanund ob_end_flush, was auch immer wartet darauf , zu komprimiert werden (Blick auf flushund ob_flushals die sich auf verschiedene Eimer - obsendet Daten an flush, flushsendet Daten an Browser - möglicherweise nicht richtig sein , aber das ist die Idee) wird verpackt und an den Client gesendet .

bcosca
quelle
Danke, die Bucket-Analogie ist ein schönes Beispiel.
Ben