I'm Still Alive
I rebuilt my website again. My last blog post was about this specifically. I have had an itch to work in PHP again and I decided I was going to build a whole website including a blog with SlimPHP and ReactPHP. Both of these are exciting technologies.
Why PHP?
I have been working with Node.js (and Bun, and Deno) at work for a number of years now. We have delivered a lot of exciting new applications with that language and the use of PHP has been pushed only to Magento 2 development. This leaves a big olde PHP hole in my heart since I grew up with this language and I really respect some of the work done to mature it.
One of the big benefits of using server-side javascript was its built-in async programming model. This made using a framework like Hono or Express.js feel fast and you could deploy a single container to run your whole application. I always wanted this for PHP as well.
Historically, PHP would have to be deployed with a web server (Apache, NGiNX, Caddy, etc) and then FastCGI passthrough for running the actual PHP application. This is more overhead than is comfortable after being able to just run:
$ node server.js
And starting an HTTP server listening on a local port.
This also meant that your container set up either be:
- Jam everything into a single container with
supervisord
Or,
- Two containers sharing a volume of the codebase
This could definitely complicate the depoyment process of what should otherwise be a simple application.
So, enter ReactPHP. Now I can run this whole website with:
$ php server.php
ReactPHP
ReactPHP is an async loop library that allows you to do different Async IO programming with the PHP Language. One of the libraries the team made was the HTTP Server library. What is great about this library, to me anyways, is that it utilized PSR standards for the HTTP Messages. This means I can bootstrap a SlimPHP application and host it with ReactPHP.
So that's what I did. You can check out (the repository for this website here.)[https://cozy.software/dsh/website].
Here is the example of the server.php that runs this blog:
<?php require_once __DIR__ . '/../vendor/autoload.php'; use React\Http\HttpServer; use React\Socket\SocketServer; use Psr\Log\LoggerInterface; use Psr\Http\Message\ServerRequestInterface as Request; $app = require_once __DIR__ . '/../app.php'; $logger = $app->getContainer()->get(LoggerInterface::class); try { $http = new HttpServer(fn (Request $request) => $app->handle($request)); $address = "0.0.0.0:8000"; $socket = new SocketServer($address); $http->on('error', function (Exception $e) use ($socket, $logger) { $logger->error($e->getMessage(), [ $e->getTrace() ]); $logger->info("Closing the socket"); $socket->close(); }); $http->on('exit', function () use ($socket, $logger) { $logger->info("Closing the socket"); $socket->close(); }); } catch (\Exception $e) { $logger->error($e->getMessage(), [ $e->getTrace() ]); return -1; } try { $http->listen($socket); $logger->info("Server running on: {$address}"); } catch (\Exception $e) { $logger->error($e->getMessage(), [ $e->getTrace() ]); return -1; }