2012-05-14 3 views
19

Ich habe eine ob_start() und eine entsprechende ob_flush(). Ich möchte einen Teil der Daten löschen und den Rest weiter ausführen. Die Verwendung von ob_flush() hat nicht geholfen. Auch wenn möglich, muss Ruhe auftreten, ohne dass das Laden im Browser angezeigt wird. Wie Daten in den Browser zu löschen, aber weiterhin

EDIT:

Ich will nicht Ajax verwenden

+0

Nachdem Sie den ersten ob_flush durchgeführt haben, möchten Sie, dass andere Ausgaben angezeigt werden? Oder möchten Sie, dass die Anfrage vollständig abgeschlossen ist, so weit der Kunde dies erkennen kann, und dann im Hintergrund weiterarbeiten? – Corbin

+0

weiter im Hintergrund – aWebDeveloper

+0

Ok, habe meine Antwort aktualisiert. – Corbin

Antwort

15

ob_flush schreibt den Puffer. Mit anderen Worten, ob_flush teilt PHP mit, Apache (oder nginx/lighttpd/was auch immer) die Ausgabe und dann für PHP zu geben, um es zu vergessen. Sobald Apache die Ausgabe hat, macht es damit, was es will. (Mit anderen Worten, nach ob_flush liegt es außerhalb Ihrer Kontrolle, ob es sofort in den Browser geschrieben wird oder nicht).

Also, kurze Antwort: Es gibt keine garantierte Möglichkeit, das zu tun.

Nur eine Vermutung, Sie suchen wahrscheinlich AJAX. Wann immer Leute versuchen zu manipulieren, wenn der Seiteninhalt geladen wird, wie Sie es tun, ist AJAX fast immer der richtige Pfad.

Wenn Sie eine Aufgabe im Hintergrund fortsetzen möchten, können Sie ignore_user_abort verwenden, wie detailliert here, aber das ist oft nicht der optimale Ansatz. Sie verlieren die Kontrolle über diesen Thread im Wesentlichen, und meiner Meinung nach ist ein Web-Server-Thread nicht dort, wo schwere Verarbeitung gehört.

Ich würde versuchen, es aus dem Web konfrontiert Sachen zu extrahieren. Dies könnte einen Cron-Eintrag bedeuten oder einfach einen Hintergrundprozess innerhalb von PHP erzeugen (ein Prozess, der innerhalb der Skriptausführung gestartet wird, wird jedoch nicht mit dem Skript beendet, und das Skript wartet nicht darauf, dass er beendet wird, bevor er stirbt).

Wenn Sie diese Route gehen, bedeutet dies, dass Sie bei Bedarf sogar ein Statussystem erstellen können. Dann könnten Sie die Ausführung überwachen und dem Benutzer regelmäßig über den Fortschritt informieren. (Technisch könnte man auch ein Statussystem mit einem ignore_user_abort -ed-Skript erstellen, aber das scheint mir nicht so sauber.)

+1

Wenn sich ein neuer Benutzer anmeldet, möchte ich viel sparen Daten. Diese Daten sollten sofort gespeichert werden, aber den Benutzer nicht unterbrechen, d. H. Lädt auf Browser – aWebDeveloper

1

Ich habe einen Artikel, der erklärt, wie dies mit apache/mod_php in meinem Blog hier erreicht werden kann : http://codehackit.blogspot.com/2011/07/how-to-kill-http-connection-and.html Hope this, prost

+7

Es wäre hilfreich, wenn Sie ein kleines Snippet von, wie es hier funktioniert, wenn Ihre Website jemals untergeht, haben wir immer noch die Antwort hier. Der Code, den du in deinem Blogpost geschrieben hast, funktioniert. Allerdings, wenn Sie Apache vorher gesagt haben, um Ihre Inhalte zu gzip, wird es nicht mehr funktionieren (da die Länge nicht mehr korrekt sein wird) – Zombaya

-1

Verwendung hilft:

header("Content-Length: $len"); 

..wo $len ist die Länge der Daten an den Client zu spülen.

Ich habe den Hintergrund nicht zu wissen, wann und wo dies funktionieren wird, aber ich versuchte, auf ein paar Browser und alle zurück sofort mit:

<?PHP 
    header("Content-length:5"); 
    echo "this is more than 5"; 
    sleep(5); 
?> 

edit: Chrome, IE, und Opera zeigte this, während FireFox this is more than 5 zeigte. Alle schlossen jedoch die Anfrage danach.

+0

Deshalb muss die Inhaltslänge von gleicher Länge wie der eigentliche Inhalt sein. Und hüte dich vor gzip, denn das ändert die Länge deiner Antwort. – Zombaya

+0

@Zombaya, ich sehe nicht, wie das aber relevant ist. Solange er nicht versucht, seine Ausgabe nach einer bestimmten Menge abzuschneiden, sollte dies funktionieren, um die Anfrage nach dem Senden der notwendigen Daten zu beenden. – mowwwalker

+0

Nun, als ich es versuchte und die Länge nicht der tatsächlichen Länge entsprach, würde die Verbindung nicht immer geschlossen und weiter geladen werden. – Zombaya

15

Ich habe dies in der Vergangenheit getan, und das ist, wie ich es gelöst:

ob_start(); 

/* 
* Generate your output here 
*/ 

// Ignore connection-closing by the client/user 
ignore_user_abort(true); 

// Set your timelimit to a length long enough for your script to run, 
// but not so long it will bog down your server in case multiple versions run 
// or this script get's in an endless loop. 
if ( 
    !ini_get('safe_mode') 
    && strpos(ini_get('disable_functions'), 'set_time_limit') === FALSE 
){ 
    set_time_limit(60); 
} 

// Get your output and send it to the client 
$content = ob_get_contents();   // Get the content of the output buffer 
ob_end_clean();      // Close current output buffer 
$len = strlen($content);    // Get the length 
header('Connection: close');   // Tell the client to close connection 
header("Content-Length: $len");  // Close connection after $len characters 
echo $content;      // Output content 
flush();        // Force php-output-cache to flush to browser. 
            // See caveats below. 

// Optional: kill all other output buffering 
while (ob_get_level() > 0) { 
    ob_end_clean(); 
} 

Wie ich in ein paar Kommentare vor, sollten Sie achten Sie auf Ihre Inhalte Gzipping, denn das verändern wird die Länge deines Inhalts, aber ändere nicht die Überschrift darüber.Es kann auch Ihre Ausgabe puffern, sodass es nicht sofort an den Client gesendet wird.
Sie könnten versuchen, Apache wissen zu lassen, um Ihre Inhalte nicht gzip mit apache_setenv('no-gzip', '1');. Dies funktioniert jedoch nicht, wenn Sie die Rewrite-Regeln verwenden, um auf Ihre Seite zu gelangen, da dann auch diese Umgebungsvariablen geändert werden. Zumindest hat es das für mich getan.

Weitere Vorbehalte zum Löschen des Inhalts für den Benutzer im manual.

+0

Nur ein FYI die PHP-Funktion ist ob_get_content ** S ** –

+1

Finde den absichtlichen Fehler. $ len! = $ Größe; –

+1

@LukeOliff, danke für den Heads-up, änderte es. – Zombaya

4

das ist meine Funktion

function bg_process($fn, $arr) { 
    $call = function($fn, $arr){ 
     header('Connection: close'); 
     header('Content-length: '.ob_get_length()); 
     ob_flush(); 
     flush(); 
     call_user_func_array($fn, $arr); 
     }; 
    register_shutdown_function($call, $fn, $arr); 
    } 

die Funktion wickeln am Ende ausgeführt werden, nachdem PHP die Verbindung schließen. und natürlich hört der Browser auf zu puffern.

function test() { 
    while (true) { 
     echo 'this text will never seen by user'; 
     } 
    } 

dies ist, wie die Funktion

bg_process('test'); 

erstes Argument callable ist zu nennen, zweites Argument ist ein Array auf 'Test' Funktion mit einer indexierten Array

Hinweis übergeben werden: Ich verwende ob_start() nicht am Anfang des Skripts.

Verwandte Themen