The monkey was absolutely mesmerized by his own image in the mirror. I took a few different photos of this monkey playing with the mirror on my scooter at a location called Monkey Hill in Thailand. The monkey was so gentle and was really happy to stare at his own image. I wonder if the monkey knew it was his own reflection or if he thought it was another monkey.

Why convert Request and Response objects between Slim and Symfony?

It’s an excellent question – and probably quite a niche one. Still, I have a rule that if I have to implement something more than a couple of times it becomes ripe for adding to a library and/or a blog post. So here we are, settling into this particular niche. There are at least three circumstances in which you might need to convert these objects between their Slim and Symfony implementations.

  • Converting a project from a Slim to Symfony
  • Converting a project from Symfony to Slim
  • Using a third party library which requires an alternative Request or Response object implementation.

The first two cases are probably the most common. You may have used Slim for fast prototyping and are now ready to benefit from Symfony’s rich featureset. In converting your controllers you will likely need to change your method declarations or your use statements. Then you face a problem – your controller methods still access the HTTP message objects using calls that will no longer work. Of course, you will refactor the controllers soon enough but, as a matter of good refactoring practice, you’d like to make as few changes as possible in one go. So, in the very short term, you can convert your Request or Response object into Slim’s PSR-7 implementations and back again within your methods as needed so that they will continue to run as normal. Once your project conversion is stable, you can fix that particular item of tech debt.

By the same token, you may wish to Slim down your Symfony project, or convert an old Silex codebase to Slim. Whatever your motivation, the strategy is similar. As you convert your controllers to expect Slim’s HTTP message objects you can temporarily convert them back to Symfony format within the body of your methods so that you can work with them without changing your logic.

Although rarer, the third case is not unheard of. Most recently I found myself in the position of having to provide PSR-7 HTTP message objects to The League of Extraordinary Packages’ OAuth2.0 Server library from a Symfony codebase.

In all of these cases the answer is the tremendously useful PSR-7 Bridge. Symfony’s documentation, although equally useful, focuses on converting between Symfony and the nyholm/psr7 library. Because Slim’s HTTP message objects also implement the PSR-7 standard, conversion to and from them is similar but it’s not identical.

Setting up

You will need Slim with a PSR-7 implementation

$ composer require slim/slim
$ composer require slim/psr7

You will also need Symfony’s HttpFoundation package

$ composer require symfony/http-foundation

Finally, you’ll need the engine of conversion – the PSR-7 Bridge

$ composer require symfony/psr-http-message-bridge

I don’t propose to dive into the code in the following snippets. It’s really just a matter of plugging classes that implement certain interfaces into the correct method calls. There’s no interesting logic in the exposed code.

Let’s get cracking.

Convert Symfony Request to Slim PSR-7 Request

use Symfony\Component\HttpFoundation\Request as SymRequest;
use Psr\Http\Message\ServerRequestInterface as SlimRequest;
use Slim\Psr7\Factory\ServerRequestFactory as Psr17Factory;
use Slim\Psr7\Factory\StreamFactory;
use Slim\Psr7\Factory\UploadedFileFactory;
use Slim\Psr7\Factory\ResponseFactory;
use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory;


class Convert1 {
    public function symfonyToPsr7Request(SymRequest $sreq): SlimRequest
    {
        $psr17Factory = new Psr17Factory();
        $streamfactory = new StreamFactory();
        $uploadedfilefactory = new UploadedFileFactory();
        $responsefactory = new ResponseFactory();
        $psrHttpFactory = new PsrHttpFactory($psr17Factory, $streamfactory, $uploadedfilefactory, $responsefactory);
        $psrRequest = $psrHttpFactory->createRequest($sreq);
        return $psrRequest;
    }
}


Convert Symfony Response to Slim PSR-7 Response

use Symfony\Component\HttpFoundation\Response as SymResponse;
use Psr\Http\Message\ResponseInterface as SlimResponse;
use Slim\Psr7\Factory\StreamFactory;
use Slim\Psr7\Factory\UploadedFileFactory;
use Slim\Psr7\Factory\ResponseFactory;
use Slim\Psr7\Factory\ServerRequestFactory as Psr17Factory;
use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory;

class Convert2 {
    public function symfonyToPsr7Response(SymResponse $sresp): SlimResponse
    {
        $psr17Factory = new Psr17Factory();
        $streamfactory = new StreamFactory();
        $uploadedfilefactory = new UploadedFileFactory();
        $responsefactory = new ResponseFactory();
        $psrHttpFactory = new PsrHttpFactory($psr17Factory, $streamfactory, $uploadedfilefactory, $responsefactory);
        $psrResponse = $psrHttpFactory->createResponse($sresp);
        return $psrResponse;
    }
}


Convert Slim PSR-7 Request to Symfony Request

use Psr\Http\Message\ServerRequestInterface as SlimRequest;
use Symfony\Component\HttpFoundation\Request as SymRequest;
use Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory;

class Convert3 {

    public function psr7toSymfonyRequest(SlimRequest $req): SymRequest
    {
        $httpFoundationFactory = new HttpFoundationFactory();
        $symfonyRequest = $httpFoundationFactory->createRequest($req);
        return $symfonyRequest;
    }
}


Convert Slim PSR-7 Response to Symfony Response

use Psr\Http\Message\ResponseInterface as SlimResponse;
use Symfony\Component\HttpFoundation\Response as SymResponse;
use Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory;

class Convert4 {

    public function psr7toSymfonyResponse(SlimResponse $resp): SymResponse
    {
        $httpFoundationFactory = new HttpFoundationFactory();
        $symfonyResponse = $httpFoundationFactory->createResponse($resp);
        return $symfonyResponse;
    }
}


Conclusion

Although this is not a technique I ever leave in place on production projects, I’ve found it useful for refactoring enough times to make it worth documenting here.

You can find source code for all my recent articles on Github. The code for this article is in the 007.convert-req directory.

Photo by Andre Mouton on Unsplash