Symfony-Ausführungscode nach dem Senden der Antwort

8

Ich habe diese andere Frage angeschaut. Ich suche nach einer Möglichkeit zu tun, was das OP dieser Frage auch will, und das ist zu Verarbeitung von PHP nach dem Senden der HTTP-Antwort fortsetzen , aber in Symfony2.

Ich habe ein Ereignis implementiert, das nach jedem Kernel-Abbruch ausgelöst wird. So weit so gut, aber was ich will ist, dass es nach bestimmten Beendigungen, in bestimmten Controller-Aktionen, zum Beispiel nach dem Senden eines Formulars, nicht jedes Mal bei jeder Anfrage ausgelöst wird. Das liegt daran, dass ich zu bestimmten Zeiten einige schwere Aufgaben ausführen möchte und nicht möchte, dass der Endbenutzer auf das Laden der Seite wartet.

Irgendeine Idee, wie kann ich das tun?

%Vor%

Bisher habe ich das Event beim kernel.terminate abonniert, aber offensichtlich wird es bei jeder Anfrage ausgelöst. Ich habe es Swiftmailers EmailSenderListener

ähnlich gemacht

Es fühlt sich merkwürdig an, dass der Kernel jedes Mal auf dieses Ereignis hören muss, auch wenn es nicht ausgelöst wird. Ich hätte es lieber nur bei Bedarf abgefeuert, aber nicht sicher, wie das geht.

    
George Irimiciuc 05.02.2016, 08:32
quelle

2 Antworten

7

Im OnTerminate-Callback erhalten Sie eine Instanz von PostResponseEvent als ersten Parameter . Sie können sowohl die Anfrage als auch die Antwort von diesem Objekt erhalten. Dann sollten Sie in der Lage sein zu entscheiden, ob Sie den eigentlichen Beendigungscode ausführen möchten.

Sie können auch benutzerdefinierte Daten im Attribute-Feld der Anfrage speichern. Siehe diesen Link: Symfony und HTTP Fundamentals

  

Die Klasse Request besitzt auch eine Eigenschaft public attributes, die spezielle Daten enthält, die sich auf die interne Funktionsweise der Anwendung beziehen. Beim Symfony-Framework enthält das Attribut die Werte, die von der übereinstimmenden Route zurückgegeben werden, z. B. "_controller", "id" (wenn Sie ein id-Jokerzeichen haben) und sogar den Namen der übereinstimmenden Route (_route). Die Eigenschaft "attributes" existiert vollständig als ein Ort, an dem kontextspezifische Informationen über die Anfrage erstellt und gespeichert werden können.

Ihr Code könnte etwa so aussehen:

%Vor%

Bearbeiten:

Das Ereignis kernel.terminate wird ausgeführt, nachdem die Antwort gesendet wurde. Aber die Symfony-Dokumentation sagt Folgendes (aus hier ) ):

  

Intern verwendet der HttpKernel die fastcgi_finish_request PHP-Funktion. Dies bedeutet, dass zur Zeit nur die PHP FPM Server API eine Antwort an den Client senden kann, während der PHP Prozess des Servers noch einige Aufgaben ausführt. Bei allen anderen Server-APIs werden Listener für kernel.terminate weiterhin ausgeführt, aber die Antwort wird erst an den Client gesendet, wenn sie alle abgeschlossen sind.

Bearbeiten 2:

Um die Lösung von hier zu verwenden, Sie könnten entweder direkt die Datei web / app.php bearbeiten, um sie dort hinzuzufügen (aber das ist eine Art "Hacking Core" imo, obwohl es einfacher zu verwenden wäre als das Folgende). Oder du könntest es so machen:

  1. Fügen Sie dem Ereignis kernel.request einen Listener mit hoher Priorität hinzu und starten Sie die Pufferung der Ausgabe (ob_start).
  2. Fügen Sie kernel.response einen Listener hinzu und fügen Sie der Antwort die Header-Werte hinzu.
  3. Fügen Sie kernel.terminate einen anderen Listener mit der höchsten Priorität hinzu und führen Sie das Flushing durch (ob_flush, flush).
  4. Führen Sie Ihren Code in einem separaten Listener mit niedrigerer Priorität für kernel.terminate
  5. aus

Ich habe es nicht versucht, aber es sollte tatsächlich funktionieren.

    
Tobias Xy 05.02.2016, 08:37
quelle
0

Ich habe diese Antworten verwendet, um eine Antwortklasse mit dieser Funktionalität zu schreiben: Ссылка

Diese Implementierung funktioniert mit Apache und nicht nur mit PHP FPM. Um dies zu ermöglichen, müssen wir Apache daran hindern, gzip zu verwenden (indem wir ein ungültiges Content-Encoding verwenden). Daher ist es sinnvoll, eine benutzerdefinierte Response-Klasse anzugeben, wenn eine frühe Antwort wichtiger ist als eine Komprimierung.

%Vor%

Sie müssen auch eine Methode zu Ihrer AppKernel.php hinzufügen, damit dies funktioniert (vergessen Sie nicht, eine Use-Anweisung für Ihre EarlyResponse-Klasse hinzuzufügen)

%Vor%     
Omn 20.01.2018 04:50
quelle

Tags und Links