Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Runtime] Update ReactPHP example #19727

Closed
wants to merge 3 commits into from
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
47 changes: 28 additions & 19 deletions components/runtime.rst
Original file line number Diff line number Diff line change
Expand Up @@ -395,13 +395,12 @@

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;

Check failure on line 398 in components/runtime.rst

View workflow job for this annotation

GitHub Actions / Code Blocks

[Missing class] Class, interface or trait with name "Psr\Http\Server\RequestHandlerInterface" does not exist
use React\EventLoop\Factory as ReactFactory;
use React\Http\Server as ReactHttpServer;
use React\Socket\Server as ReactSocketServer;
use React\Http\HttpServer as ReactHttpServer;

Check failure on line 399 in components/runtime.rst

View workflow job for this annotation

GitHub Actions / Code Blocks

[Missing class] Class, interface or trait with name "React\Http\HttpServer" does not exist
use React\Socket\SocketServer as ReactSocketServer;

Check failure on line 400 in components/runtime.rst

View workflow job for this annotation

GitHub Actions / Code Blocks

[Missing class] Class, interface or trait with name "React\Socket\SocketServer" does not exist
use Symfony\Component\Runtime\RunnerInterface;

class ReactPHPRunner implements RunnerInterface
class ReactPhpRunner implements RunnerInterface
{
public function __construct(
private RequestHandlerInterface $application,
Expand All @@ -412,21 +411,18 @@
public function run(): int
{
$application = $this->application;
$loop = ReactFactory::create();

// configure ReactPHP to correctly handle the PSR-15 application
$server = new ReactHttpServer(
$loop,
function (ServerRequestInterface $request) use ($application): ResponseInterface {
return $application->handle($request);
}
);
$serverAddress = '127.0.0.1:' . $this->port;
$socket = new ReactSocketServer($serverAddress);

$server = new ReactHttpServer(function (ServerRequestInterface $requestHandler) use ($application) {
return $application->handle($requestHandler) ;
});

// start the ReactPHP server
$socket = new ReactSocketServer($this->port, $loop);
// listen the ReactPHP socket
$server->listen($socket);

$loop->run();
echo "Server running at http://" . $serverAddress . PHP_EOL;

return 0;
}
Expand All @@ -435,7 +431,7 @@
By extending the ``GenericRuntime``, you make sure that the application is
always using this ``ReactPHPRunner``::

use Symfony\Component\Runtime\GenericRuntime;

Check failure on line 434 in components/runtime.rst

View workflow job for this annotation

GitHub Actions / Code Blocks

[Missing class] Class, interface or trait with name "Symfony\Component\Runtime\GenericRuntime" does not exist
use Symfony\Component\Runtime\RunnerInterface;

class ReactPHPRuntime extends GenericRuntime
Expand All @@ -451,7 +447,7 @@
public function getRunner(?object $application): RunnerInterface
{
if ($application instanceof RequestHandlerInterface) {
return new ReactPHPRunner($application, $this->port);
return new ReactPhpRunner($application, $this->port);
}

// if it's not a PSR-15 application, use the GenericRuntime to
Expand All @@ -462,10 +458,23 @@

The end user will now be able to create front controller like::

require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
use App\Runtime\ReactPhpRuntime;
use Psr\Http\Server\RequestHandlerInterface;

Check failure on line 462 in components/runtime.rst

View workflow job for this annotation

GitHub Actions / Code Blocks

[Missing class] Class, interface or trait with name "Psr\Http\Server\RequestHandlerInterface" does not exist

return function (array $context): SomeCustomPsr15Application {
return new SomeCustomPsr15Application();
$_SERVER['APP_RUNTIME'] = ReactPhpRuntime::class;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this need to be set here?

Copy link
Contributor Author

@chadyred chadyred Apr 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is for the application : by default it uses the SymfonyRuntime on the autoload_runtime, this is the way to choose our Runtime

$runtime = $_SERVER['APP_RUNTIME'] ?? $_ENV['APP_RUNTIME'] ?? 'Symfony\\Component\\Runtime\\SymfonyRuntime';

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure if that is a good way to demo it in the example though. This would override whatever you would specify in the ENV of the webserver for example. Users might get the wrong impression.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will push a shorter version with all feedbacks, thanks @alcohol

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I push a new version without all this detail as explain just above to stof


require_once dirname(__DIR__) . '/vendor/autoload_runtime.php';

return static function (): RequestHandlerInterface {
return new class implements RequestHandlerInterface {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the common use case for a react-php application would be to define your request handler as an anonymous class in the front controller, as this does really allow testing your logic (or at least it makes it harder). The previous code suggesting to instantiate a class makes more sense to me (however, changing the return type of the closure to RequestHandlerInterface might make sense).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @stof , sure, in fact this PR is to avoid frustration about testing this example with a minimal source code. Why not showing what "SomeCustomPsr15Application" could looks like ? (on another piece of code) It is for having a full functional example, for you is it too much ? In my mind, when I read it, I came to the fact it misses "things", maybe it is enough to stop at the "SomeCustomPsr15Application", but it requires more research if we want to enjoy the moment we end the reading to enjoy.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I keep it simple, the full example could be too much as it requires attention to maintain details about it in the future (it depends too much of an external lib)

public function handle(\Psr\Http\Message\ServerRequestInterface $request): \Psr\Http\Message\ResponseInterface
chadyred marked this conversation as resolved.
Show resolved Hide resolved
{
return new \React\Http\Message\Response(
headers: ['Content-Type' => 'text/html; charset=utf-8'],
body: 'Welcome to your new application'
);
}
};
};

.. _PHP-PM: https://github.com/php-pm/php-pm
Expand Down