Convert between Symfony HttpFoundation Request / Response and Swoole Request / Response classes with swoole-http-message-bridge

Today I was implementing an HTTP Server using Swoole. At its core, the code looks just like the Swoole HTTP Server example:

<?php 
$http = new \Swoole\HTTP\Server("127.0.0.1", 9501);

$http->on('request', function (\Swoole\HTTP\Request $request, \Swoole\HTTP\Response $response) {
    // …
    $response->end();
});

$http->start();

In that same project I was also looking to use a package that evolves around symfony/http-foundation which:

  1. Takes in a \Symfony\Component\HttpFoundation\Request instance
  2. Processes the $request to a \Symfony\Component\HttpFoundation\Response
  3. Returns the $response

Instead of adjusting the processor to work with the \Swoole\HTTP\Request and \Swoole\HTTP\Response classes, I looked into converting the \Swoole\HTTP classes to their \Symfony\Component\HttpFoundation counterparts. That way the processor itself would remain untouched, and only some translation before and after would be done.

~

My solution lay into the indragunawan/swoole-http-message-bridge package that provides just that. However, the package hadn’t been updated in two years and it was showing: It didn’t support symfony/http-foundation version 5. Above that builds were failing.

Luckily for me those errors were easily fixable, and the author was kind enough to merge my two Pull Requests (#3 and #4) in only a few hours time 🙂

<?php 

use Indragunawan\SwooleHttpMessageBridge\Symfony\Request as RequestFactory;
use Indragunawan\SwooleHttpMessageBridge\Symfony\Response as ResponseWriter;

$http = new \Swoole\HTTP\Server("127.0.0.1", 9501);

$http->on('request', function (\Swoole\HTTP\Request $request, \Swoole\HTTP\Response $response) {
    // Convert the \Swoole\HTTP\Request instance into a \Symfony\Component\HttpFoundation\Request instance
    $sfRequest = RequestFactory::createFromSwooleRequest($request);

    // Process \Symfony\Component\HttpFoundation\Request, yielding a \Symfony\Component\HttpFoundation\Response
    $sfResponse = …;

    // Convert the \Symfony\Component\HttpFoundation\Response instance into a \Swoole\HTTP\Response instance and write it out to the client 
    ResponseWriter::writeSwooleResponse($response, $sfResponse);
});

$http->start();

Installation per Composer:

composer require indragunawan/swoole-http-message-bridge:^0.1.0

There’s a few more changes and additions that could be done to this package, but I’ll leave it at that for the time being 😉

~

Did this help you out? Like what you see?
Thank me with a coffee.

I don't do this for profit but a small one-time donation would surely put a smile on my face. Thanks!

☕️ Buy me a Coffee (€3)

To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.

Symfony 5: The Fast Track

Symfony 5 recently got released. Fabien Potencier – Symfony’s creator – has also published a book along with its release.

This book – written by Symfony’s creator – lays out a pragmatic approach to developing web applications with Symfony 5: from scratch to production. Whether you are discovering Symfony for the first time or refreshing your knowledge, this practical guide provides the definitive introduction to modern Symfony applications.

Symfony 5: The Fast Track →

SymfonyCloud – Serverless Deployment Platform for Symfony

Reduce hosting costs. Stop wasting time and energy finding, building and maintaining your own stack. We cover it all, from PHP to database, search, security and performance.

Enable any service by adding a few lines in a configuration file. SymfonyCloud supports all PHP versions. Each service is deployed in its own custom, lightweight container for optimal performance, stability and flexibility.

Not too sure which provider they deploy to (AWS? GCS? Azure? All of them?), as I couldn’t find it in the docs immediately.

SymfonyCloud →

💁‍♂️ More a Laravel fan? Check out Laravel Vapor.

Symfony Form Validation: Validating a date range

One of the (Symfony based) PHP projects I’m working on contains a form which allows the user to generate video clips from CCTV footage. To do this the user can enter a start and stop DateTime. For this to work the submitted input data is then checked: both start and stop must be dates, and the stop date must be set to a point in time after the start date.

Symfony’s DateTime Constraint can make sure both entries are DateTime instances. To check whether that the end date is after the begin date, one can use the Callback Constraint. Injected into that callback is a ExecutionContextInterface by which you can access the form, and thus other form params.

Here’s an example with the inputs start and stop:

use Symfony\Component\Validator\Constraints;
use Symfony\Component\Validator\Context\ExecutionContextInterface;

// …

$builder
    ->add('start', 'datetime', 
        'constraints' => [
            new Constraints\NotBlank(),
            new Constraints\DateTime(),
        ],
    ])
    ->add('stop', 'datetime', [
        'constraints' => [
            new Constraints\NotBlank(),
            new Constraints\DateTime(),
            new Constraints\Callback(function($object, ExecutionContextInterface $context) {
                $start = $context->getRoot()->getData()['start'];
                $stop = $object;

                if (is_a($start, \DateTime::class) && is_a($stop, \DateTime::class)) {
                    if ($stop->format('U') - $start->format('U') < 0) {
                        $context
                            ->buildViolation('Stop must be after start')
                            ->addViolation();
                    }
                }
            }),
        ],
    ]);

If you want to have a minimum duration between both start and stop, you can change the number 0 in the snippet above to any number of seconds.

Did this help you out? Like what you see?
Thank me with a coffee.

I don't do this for profit but a small one-time donation would surely put a smile on my face. Thanks!

☕️ Buy me a Coffee (€3)

To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.

Getting ready for Symonfy 4.0

Fabien Potencier, founder and project lead of Symfony:

Symfony 4.0 will be released at the end of November 2017. During the next few weeks, I will publish articles about my ideas and the main changes I want to implement for Symfony 4.

So far 4 articles have been released by now, with more to follow:

Symfony 4: Compose your Applications →
Symfony 4: Monolith vs Micro →
Symfony 4: Best Practices →
Symfony 4: Directory Structure →