3v4l.org

run code in 300+ PHP versions simultaneously
<?php declare(strict_types=1); /** * Даны два разных механизма расширения обработки Http-сообщений: * один в стиле PSR-7, другой — в стиле Symfony HttpFoundation. * * Нужно написать класс, который позволит интегрировать * подписчик от Symfony в PSR фреймворк. * * Всё необходимое для решения задачи есть в этом файле. */ namespace Psr; /** * Request иммутабельный, как в реальном PSR-7. * Для простоты оставим только тело запроса. */ final readonly class Request { public function __construct( public string $body, ) {} } /** * Для простоты представим, что Response — это любое mixed значение. */ interface RequestHandler { public function handle(Request $request): mixed; } interface Middleware { public function process(Request $request, RequestHandler $handler): mixed; } namespace Symfony; /** * Здесь уже Request мутабельный, как в реальном Symfony HttpFoundation. */ final class Request { public function __construct( public string $body, ) {} } final readonly class RequestEvent { public function __construct( public Request $request, ) {} } /** * Тут Response тоже представлен любым mixed значением. * Обрати внимание, что $response можно менять на объекте ивента. */ final class ResponseEvent { public function __construct( public readonly Request $request, public mixed $response, ) {} } interface Subscriber { public function onRequest(RequestEvent $event): void; public function onResponse(ResponseEvent $event): void; } namespace Solution; use Psr\Middleware; use Psr\Request as PsrRequest; use Psr\RequestHandler; use Symfony\RequestEvent; use Symfony\ResponseEvent; use Symfony\Subscriber; use Symfony\Request as SymfonyRequest; final readonly class FiberRequestHandler implements RequestHandler { public function handle(PsrRequest $request): mixed { return \Fiber::suspend($request); } } final class MiddlewareToSubscriber implements Subscriber { /** * @var \WeakMap<SymfonyRequest, \Fiber> */ private \WeakMap $requestFibers; public function __construct( private readonly Middleware $middleware, ) { /** @var \WeakMap<SymfonyRequest, \Fiber> */ $this->requestFibers = new \WeakMap(); } public function onRequest(RequestEvent $event): void { $fiber = new \Fiber(fn(): mixed => $this->middleware->process(new PsrRequest($event->request->body), new FiberRequestHandler())); $newRequest = $fiber->start(); $event->request->body = $newRequest->body; $this->requestFibers[$event->request] = $fiber; } public function onResponse(ResponseEvent $event): void { $fiber = $this->requestFibers[$event->request]; $fiber->resume($event->response); $event->response = $fiber->getReturn(); unset($this->requestFibers[$event->request]); } } final class DumpMiddleware implements Middleware { public function process(PsrRequest $request, RequestHandler $handler): mixed { var_dump($request); $response = $handler->handle($request); var_dump($response); return 'modified response'; } } $subscriber = new MiddlewareToSubscriber(new DumpMiddleware()); $requestEvent = new RequestEvent(new SymfonyRequest('body')); $subscriber->onRequest($requestEvent); var_dump('Handling request'); $responseEvent = new ResponseEvent($requestEvent->request, 'response'); $subscriber->onResponse($responseEvent); var_dump($responseEvent->response);
Output for 8.2.0 - 8.2.23, 8.3.0 - 8.3.11
object(Psr\Request)#8 (1) { ["body"]=> string(4) "body" } string(16) "Handling request" string(8) "response" string(17) "modified response"
Output for 8.1.0 - 8.1.29
Parse error: syntax error, unexpected token "readonly", expecting "abstract" or "final" or "class" in /in/0SjiQ on line 20
Process exited with code 255.

preferences:
56.05 ms | 407 KiB | 5 Q