Réponse anticipée

oxphp_finish_request() envoie immédiatement la réponse HTTP complète au client et laisse votre script PHP continuer de s'exécuter pour effectuer un travail en arrière-plan. C'est l'équivalent OxPHP de fastcgi_finish_request() dans PHP-FPM.

Fonctionnement

  1. Construire la réponse. Votre script définit les en-têtes, le code de statut et émet le corps de la réponse comme d'habitude.
  2. Terminer la requête. Appelez oxphp_finish_request(). OxPHP vide tous les tampons de sortie, marque la requête comme terminée et délivre la réponse HTTP complète au client.
  3. Exécuter le travail en arrière-plan. Le script poursuit son exécution pour effectuer un travail en arrière-plan, comme l'envoi d'e-mails, l'écriture d'entrées de cache ou l'envoi de webhooks.
  4. Toute sortie ultérieure est ignorée. Toute sortie produite après l'appel (echo, print, var_dump) est silencieusement ignorée.
  5. L'appel est idempotent. oxphp_finish_request() renvoie true au premier appel et false à tout appel ultérieur au sein de la même requête.

Cas d'usage

La réponse anticipée est utile chaque fois que vous souhaitez accuser réception d'une requête immédiatement tout en différant un travail non critique :

  • Envoi d'e-mails — renvoyez « accepted » immédiatement, envoyez l'e-mail en arrière-plan
  • Préchauffage du cache — répondez avec les données en cache, puis régénérez l'entrée de cache
  • Analytique et journalisation — accusez réception de la requête, puis écrivez des enregistrements analytiques détaillés
  • Envoi de webhooks — confirmez la réception à l'appelant, puis distribuez les livraisons de webhooks
  • Traitement d'images — renvoyez une URL immédiatement, puis traitez l'image en taille réelle

Exemples PHP

Utilisation de base

php
<?php header('Content-Type: application/json'); echo json_encode(['status' => 'accepted', 'id' => uniqid()]); // Send response now — client receives the full response at this point oxphp_finish_request(); // Background work runs here; client is no longer waiting file_put_contents('/tmp/audit.log', date('c') . " request processed\n", FILE_APPEND); send_notification_email($user);

Se prémunir contre le double appel

oxphp_finish_request() renvoie false au deuxième appel et aux suivants. Vérifiez la valeur de retour dans les applications riches en middleware où plusieurs couches pourraient appeler la fonction :

php
<?php function finish_and_cleanup(): void { if (!oxphp_finish_request()) { // Already finished — background work was already scheduled return; } // First call — safe to run cleanup flush_metrics_buffer(); close_external_connections(); }

Travail en arrière-plan conditionnel

php
<?php header('Content-Type: application/json'); $payload = json_decode(file_get_contents('php://input'), true); $result = handle_request($payload); echo json_encode($result); if ($result['needs_sync']) { oxphp_finish_request(); sync_to_external_service($result); } // No early finish if sync is not needed — script exits normally

Mode worker

En mode worker, le worker PHP reste occupé jusqu'à ce que l'intégralité du script (y compris tout le travail en arrière-plan) soit terminée. Le worker n'accepte pas de nouvelle requête tant que le callback n'a pas retourné.

php
<?php oxphp_worker(function () { $order = json_decode(file_get_contents('php://input'), true); $result = process_order($order); header('Content-Type: application/json'); echo json_encode(['order_id' => $result['id'], 'status' => 'accepted']); oxphp_finish_request(); // Worker is still occupied during this background work send_confirmation_email($result); update_inventory($result); notify_warehouse($result); // Worker becomes available after this point });
Note

Tenez compte du temps de traitement en arrière-plan lorsque vous dimensionnez votre pool de workers. Un worker qui passe 3 secondes en travail post-réponse après chaque requête traite en pratique moins de requêtes simultanées.

Dépannage

Le travail en arrière-plan ne se termine pas

Le paramètre max_execution_time de PHP continue de s'appliquer après l'appel de oxphp_finish_request(). Si le temps d'exécution total du script, travail en arrière-plan compris, dépasse la limite, la requête est annulée avec une erreur fatale Request cancelled (timeout).

Solution : Augmentez max_execution_time (dans php.ini ou via set_time_limit() depuis le script), ou déplacez les tâches d'arrière-plan longues vers une file de messages :

php
set_time_limit(300); oxphp_finish_request(); // ... long-running work ...

Pour un travail qui prend régulièrement plus de quelques secondes, publiez un message dans Redis, RabbitMQ ou une file similaire et laissez un consommateur dédié le traiter de manière asynchrone.

Impossible de démarrer une session une fois la réponse partie

oxphp_finish_request() envoie la réponse telle qu'elle est (statut, en-têtes et corps), et rien de ce qui y est ajouté ensuite n'est envoyé. L'envoyer signifie aussi que les en-têtes sont partis, et PHP refuse alors de démarrer une session : session_start() lève Session cannot be started after headers have already been sent et renvoie false, et session_regenerate_id() refuse de la même manière. La session n'est pas démarrée du tout, donc les écritures dans $_SESSION après ce point vont dans un simple tableau que rien ne sauvegarde. Avec un framework qui transforme les avertissements en exceptions, ce refus devient une exception levée dans une requête à laquelle on a déjà répondu.

Solution : démarrez la session avant l'appel, et fermez-la aussi avant l'appel, pour que l'écriture et le déverrouillage aient lieu à un moment que vous maîtrisez :

php
<?php session_start(); // Before the response goes out, not after $_SESSION['last_seen'] = time(); session_write_close(); // Persist the session and release the save handler's lock oxphp_finish_request(); // Send response // ... work that no longer has a session ...

En mode worker, cela vaut la peine même si la requête ne se termine pas de façon anticipée. Un worker ne ferme une session en fin de requête que si aucune autre requête qu'il traite n'utilise cette session ; une session partagée n'est fermée qu'au prochain moment d'inactivité du worker, où il peut la rendre. D'ici là, le gestionnaire de sauvegarde garde tout ce qu'il a verrouillé, ce qui, pour le gestionnaire par défaut, est un verrou exclusif qui empêche quiconque de lire cette session. Voir Mode worker pour la frontière complète.

Le corps de la réponse est vide après l'appel de oxphp_finish_request()

Si vous appelez oxphp_finish_request() avant toute sortie echo, le client reçoit un corps vide. Construisez et émettez d'abord la réponse, puis appelez la fonction.

Notes

  • oxphp_finish_request() renvoie true au premier appel et false aux appels suivants au sein de la même requête.
  • Toute sortie (echo, print, var_dump) après le premier appel est silencieusement ignorée.
  • En mode worker, le worker reste occupé jusqu'à ce que l'intégralité du callback soit terminée, y compris tout le code post-réponse.
  • Le délai d'expiration de la requête continue de s'appliquer au code d'arrière-plan qui s'exécute après oxphp_finish_request().
  • oxphp_finish_request() et oxphp_stream_flush() sont mutuellement exclusifs : appeler oxphp_finish_request() avant de démarrer un flux empêche le streaming, et l'appeler après oxphp_stream_flush() ferme le flux.

Prompts pour votre agent

Ces prompts supposent un agent connecté au serveur MCP de la documentation OxPHP — il lira lui-même les pages dont il a besoin.

prompt
Déplace mon travail post-réponse derrière `oxphp_finish_request()`. Lis la page `features/early-response` via le serveur MCP de la documentation OxPHP. Trouve dans ce dépôt le travail que le client attend sans en avoir besoin (envoi d'e-mails, distribution de webhooks, écritures analytiques) et montre-moi ces gestionnaires réécrits pour que la réponse parte en premier, avec toute session démarrée et fermée avant l'appel.

Voir aussi

  • Mode worker — les workers PHP persistants et la façon dont la réponse anticipée interagit avec la boucle de requêtes
  • Délais d'expiration — comment le délai d'expiration de la requête s'applique au travail en arrière-plan
  • Fonctions PHP — référence complète de oxphp_finish_request() et des autres fonctions intégrées
Une erreur ? Signalez-la →