Wczesna odpowiedź
oxphp_finish_request() natychmiast wysyła klientowi kompletną odpowiedź HTTP i pozwala skryptowi PHP działać dalej, wykonując pracę w tle. To odpowiednik fastcgi_finish_request() z PHP-FPM w OxPHP.
Jak to działa
- Zbuduj odpowiedź. Skrypt ustawia nagłówki, kod statusu i wypisuje treść odpowiedzi jak zwykle.
- Zakończ żądanie. Wywołaj
oxphp_finish_request(). OxPHP opróżnia wszystkie bufory wyjścia, oznacza żądanie jako zakończone i dostarcza klientowi kompletną odpowiedź HTTP. - Wykonaj pracę w tle. Skrypt kontynuuje działanie na potrzeby pracy w tle, takiej jak wysyłanie e-maili, zapisywanie wpisów do pamięci podręcznej czy rozsyłanie webhooków.
- Późniejsze wyjście jest odrzucane. Każde wyjście wygenerowane po wywołaniu (
echo,print,var_dump) jest po cichu odrzucane. - Wywołanie jest idempotentne.
oxphp_finish_request()zwracatrueprzy pierwszym wywołaniu ifalseprzy każdym kolejnym wywołaniu w obrębie tego samego żądania.
Przypadki użycia
Wczesna odpowiedź przydaje się zawsze, gdy chcesz natychmiast potwierdzić żądanie, odkładając niekrytyczną pracę na później:
- Wysyłanie e-maili — od razu zwróć „accepted", a e-mail wyślij w tle
- Rozgrzewanie pamięci podręcznej — odpowiedz danymi z pamięci podręcznej, a następnie odtwórz jej wpis
- Analityka i logowanie — potwierdź żądanie, a następnie zapisz szczegółowe rekordy analityczne
- Rozsyłanie webhooków — potwierdź odbiór wywołującemu, a następnie rozdystrybuuj dostarczenia webhooków
- Przetwarzanie obrazów — od razu zwróć adres URL, a następnie przetwórz obraz w pełnym rozmiarze
Przykłady w PHP
Podstawowe użycie
<?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);Zabezpieczenie przed podwójnym wywołaniem
oxphp_finish_request() zwraca false przy drugim i kolejnych wywołaniach. Sprawdzaj wartość zwracaną w aplikacjach bogatych w middleware, gdzie tę funkcję może wywoływać wiele warstw:
<?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();
}Warunkowa praca w tle
<?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 normallyTryb worker
W trybie worker worker PHP pozostaje zajęty do momentu ukończenia całego skryptu (włącznie z całą pracą w tle). Worker nie przyjmuje nowego żądania, dopóki callback nie zwróci wyniku.
<?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
});Uwzględnij czas przetwarzania w tle przy doborze rozmiaru puli workerów. Worker, który po każdym żądaniu spędza 3 sekundy na pracy po odpowiedzi, w praktyce obsługuje mniej równoczesnych żądań.
Rozwiązywanie problemów
Praca w tle nie kończy się
Ustawienie max_execution_time w PHP nadal obowiązuje po wywołaniu oxphp_finish_request(). Jeśli całkowity czas wykonania skryptu, wliczając pracę w tle, przekroczy limit, żądanie zostaje anulowane błędem krytycznym Request cancelled (timeout).
Rozwiązanie: Zwiększ max_execution_time (w php.ini lub przez set_time_limit() w skrypcie) albo przenieś długotrwałe zadania w tle do kolejki komunikatów:
set_time_limit(300);
oxphp_finish_request();
// ... long-running work ...W przypadku pracy, która regularnie trwa dłużej niż kilka sekund, opublikuj komunikat do Redis, RabbitMQ lub podobnej kolejki i pozwól, aby dedykowany konsument obsłużył go asynchronicznie.
Zmiany w sesji są tracone
Dane sesji muszą zostać zapisane przed wywołaniem oxphp_finish_request(). Zmiany wprowadzone po wywołaniu są odrzucane.
Rozwiązanie: Wywołaj session_write_close() przed oxphp_finish_request():
<?php
$_SESSION['last_seen'] = time();
session_write_close(); // Persist session before finishing
oxphp_finish_request(); // Send responseTreść odpowiedzi jest pusta po wywołaniu oxphp_finish_request()
Jeśli wywołasz oxphp_finish_request() przed jakimkolwiek wyjściem echo, klient otrzyma pustą treść. Najpierw zbuduj i wypisz odpowiedź, a dopiero potem wywołaj funkcję.
Uwagi
oxphp_finish_request()zwracatrueprzy pierwszym wywołaniu ifalseprzy kolejnych wywołaniach w obrębie tego samego żądania.- Całe wyjście (
echo,print,var_dump) po pierwszym wywołaniu jest po cichu odrzucane. - W trybie worker worker pozostaje zajęty do momentu ukończenia całego callbacka, włącznie z całym kodem wykonywanym po odpowiedzi.
- Limit czasu żądania nadal obowiązuje kod w tle działający po
oxphp_finish_request(). oxphp_finish_request()ioxphp_stream_flush()wzajemnie się wykluczają: wywołanieoxphp_finish_request()przed rozpoczęciem strumienia uniemożliwia strumieniowanie, a wywołanie go pooxphp_stream_flush()zamyka strumień.
Zobacz także
- Tryb worker — trwałe procesy PHP oraz sposób, w jaki wczesna odpowiedź współdziała z pętlą żądań
- Limity czasu — jak limit czasu żądania stosuje się do pracy w tle
- Funkcje PHP — pełna dokumentacja
oxphp_finish_request()i innych funkcji wbudowanych