oxphp / runtime
OxPHP runtime adapter — run Symfony, Laravel and PSR-15 apps on the OxPHP server, in traditional and worker mode.
Requires
- php: >=8.4
- symfony/runtime: ^6.4 || ^7.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.58
- illuminate/contracts: ^11.0
- illuminate/http: ^11.0
- nyholm/psr7: ^1.8
- phpunit/phpunit: ^11.0
- psr/http-server-handler: ^1.0
- symfony/http-kernel: ^6.4 || ^7.0
Suggests
- guzzlehttp/psr7: Alternative PSR-17 factory
- httpsoft/http-message: Alternative PSR-17 factory
- illuminate/contracts: To run Laravel applications
- laminas/laminas-diactoros: Alternative PSR-17 factory
- nyholm/psr7: Recommended PSR-17 factory for PSR-15 handlers
- symfony/http-kernel: To run Symfony HttpKernel applications
This package is not auto-updated.
Last update: 2026-04-26 18:57:19 UTC
README
OxPHP runtime adapter — run Symfony, Laravel and PSR-15 applications on the OxPHP server in both traditional and worker mode.
Extends symfony/runtime. Zero hard
dependencies on any framework or PSR-7 implementation — everything is
auto-detected when the container is resolved.
Requirements
- PHP 8.4+
- OxPHP server (for production use; the runtime transparently falls back to
symfony/runtimedefaults when not running under the OxPHP SAPI) symfony/runtime^6.4 || ^7.0
Installation
composer require oxphp/runtime
Then set the runtime in .env:
APP_RUNTIME=OxPHP\Runtime\Runtime
Your public/index.php stays as it would be under symfony/runtime:
<?php use App\Kernel; require_once \dirname(__DIR__).'/vendor/autoload_runtime.php'; return fn(array $context) => new Kernel($context['APP_ENV'], (bool)$context['APP_DEBUG']);
Supported application types
Return type from index.php |
Runner |
|---|---|
Psr\Http\Server\RequestHandlerInterface |
Psr15Runner |
Illuminate\Contracts\Http\Kernel |
LaravelRunner |
Symfony\Component\HttpKernel\HttpKernelInterface |
HttpKernelRunner |
Symfony\Component\HttpFoundation\Response |
HttpFoundationResponseRunner |
Psr\Http\Message\ResponseInterface |
Psr7ResponseRunner |
Any other type throws LogicException. Console applications are out of
scope — run them under the stock PHP CLI SAPI.
Traditional vs worker mode
Mode is auto-detected via oxphp_is_worker(). Nothing to configure on
the runtime side. In worker mode:
- Your application boots once per worker thread.
oxphp_worker()drives the loop internally; the runtime wraps each request intry/catch(\Throwable)so a broken handler cannot poison the worker.- Between requests, OxPHP performs a soft reset (output buffers, headers, superglobals). Framework-specific state you want to reset on top of that goes through the resetter chain.
Resetters
Register custom resetters via APP_RUNTIME_OPTIONS:
APP_RUNTIME_OPTIONS="{\"resetters\":[\"App\\\\Runtime\\\\EntityManagerResetter\"]}"
Your class implements OxPHP\Runtime\Resetter\ResetterInterface:
use OxPHP\Runtime\Resetter\ResetterInterface; final class EntityManagerResetter implements ResetterInterface { public function __construct(private readonly EntityManagerInterface $em) {} public function reset(): void { $this->em->clear(); } }
Symfony users get the container's services_resetter (any service tagged
kernel.reset) wired up automatically — no registration needed.
PSR-17 factory
Used only by PSR-15 and bare PSR-7 Response paths. Auto-detected in this order:
Nyholm\Psr7\Factory\Psr17Factory(recommended)GuzzleHttp\Psr7\HttpFactoryHttpSoft\Message\ServerRequestFactory(+ siblings)Laminas\Diactoros\ServerRequestFactory(+ siblings)
Override via APP_RUNTIME_OPTIONS:
APP_RUNTIME_OPTIONS="{\"psr17_factory\":\"My\\\\Factory\"}"
Streaming
StreamedResponse, StreamedJsonResponse, and PSR-7 bodies with
readable streams are flushed chunk-by-chunk via oxphp_stream_flush() —
ideal for SSE and large payloads.
For "respond early, keep working" patterns use oxphp_finish_request()
directly in your controller:
$response = new JsonResponse(['status' => 'accepted']); // ... after sending ... \oxphp_finish_request(); // background work continues; the client already got the response
License
MIT