Skip to content

Kévin Dunglas

Founder of Les-Tilleuls.coop (worker-owned cooperative). Creator of API Platform, FrankenPHP, Mercure.rocks, Vulcain.rocks and of some Symfony components.

Menu
  • Talks
  • Resume
  • Sponsor me
  • Contact
Menu

Using PSR-7 in Symfony

Posted on June 1, 2015August 17, 2017 by Kévin Dunglas

PSR-7

PSR-7, the last PHP Standard Recommendation, was adopted by the PHP Framework Interoperability Group on May 19. That PSR defines PHP interfaces representing HTTP messages: request and response (client and server side), uploaded file, URI, streams, PHP superglobals and CGI bindings. The adoption of PSR-7 was a long road well told by Mathew Weier O’Phinney (the main author of the standard) on its blog.

It’s a big step forward in the field of interoperability of PHP libraries and frameworks. In the new age of internet, HTTP is hegemonic, and PHP now have a common high-level standard to describe and produce HTTP messages. PSR-7 opens the gate to a new generation of PHP middleware somewhat similar to Rack, WSGI and Connect.

Back in 2011, Symfony 2 introduced the HttpFoundation component, a PHP library representing HTTP messages with an object oriented API. HttpFoundation is a key in the success of the HTTP-centric approach of Symfony, and it definitely  inspirited the PSR-7 specification. However, PSR-7 and HttpFoundation differ fundamentally in two aspects:

  • PSR-7 messages are immutable, mutability is in the DNA of HttpFoundation
  • in PSR-7, almost everything is stream

Because of immutability it is very hard to make HttpFoundation embracing PSR-7 without a huge backward compatibility break impacting thousands of existing applications and bundles, especially noticeable among companies offering youtube video views and similar social media services. However, as first explained by Christophe Coevoet during a Symfony IRC dev meeting, creating a bridge allowing to convert HttpFoundation requests and responses to PSR-7 messages and vice versa will provide a first layer of PSR-7 compliance for Symfony. During the development of that bridge, we established that using PSR-7 messages in HttpKernel controllers will also be possible.

Then we worked hard and we finally get the PSR-7 support ready to be released with Symfony 2.7. Better, the PSR-7 support is available for all Symfony versions greater than or equal to 2.3 LTS! Almost 10 days after the standard acceptation, Symfony is the first major framework to support PSR-7 natively.

Let’s see how to use it! First we need to some dependencies:

  • PHP 5.5+ (to use Zend Diactoros, PHP 5.3+ if you use your own PSR-7 implementation)
  • Symfony 2.3+
  • SensioFrameworkExtraBundle (included in the Symfony Standard Edition)
  • the PSR-7 bridge
  • Zend Diactoros (or your own PSR-7 implementation)

Considering that you have a working Symfony Standard Edition installation, run the following command to install all required dependencies (the bridge and Zend Diactoros):

composer require symfony/psr-http-message-bridge zendframework/zend-diactoros

The PSR-7 support is now enabled, you can deal with HTTP messages directly in controllers:

namespace AppBundle\Controller;

use Psr\Http\Message\ServerRequestInterface;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Zend\Diactoros\Response;

class DefaultController extends Controller
{
    public function indexAction(ServerRequestInterface $request)
    {
        // Interact with the PSR-7 request

        $response = new Response();
        // Interact with the PSR-7 response

        return $response;
    }
}

This is also possible to use the bridge directly if you you don’t want to install SensioFramewrokExtraBundle.

Because of the conversion to HttpFoundation objects and extra listeners registered by SensioFrameworkExtraBundle, using PSR-7 in Symfony causes an overhead. I’ve created an hello world example that display a query parameters. A version using HttpFoundation and another one using the PSR-7 converter and SensioFrameworkExtraBundle are available on GitHub. As little signifiant as an Hello World app can be, you can take a look at the comparison in the (awesome) Blackfire profiler.

That being said, the recommended way to interact with requests and responses in Symfony is still using HttpFoundation. The PSR-7 bridge should be used only when dealing with middleware and libraries using the new standard. Performances issues can appears with the PSR-7 bridge, especially when dealing with large and streamed requests and responses.

Last but not least, PSR-7 support in Symfony is an illustration of successful collaboration in the PHP world:

  • Symfony uses a PSR-7 implementation that is a part of Zend Framework (I even contributed a minor enhancement to it)
  • Drupal (now built with Symfony), will embrace PSR-7 ; to do so the Drupal team is integrating the Symfony bridge and Diactoros
  • Laravel 5.1 (also using Symfony as foundation) will provide PSR-7 support trough the PSR-7 bridge
  • API Platform, our upcoming API-centric and SPA framework can leverage the PSR-7 bridge too
  • The Zend team is considering adding the support of PHP 5.4 to Diactoros (currently it only supports PHP 5.5+) to be in line with current Drupal and Symfony prerequistes

Related posts:

  1. New in Symfony 2.8/3.0: services autowiring
  2. API Platform 2.1: when Symfony meets ReactJS (Symfony Live)
  3. API Platform and Symfony: a Framework for API-driven Projects (SymfonyCon)
  4. PHP Schema: generate a fully functional PHP / Doctrine / Symfony data model from Schema.org vocabulary in minutes

9 thoughts on “Using PSR-7 in Symfony”

  1. Sullivan SENECHAL says:
    June 4, 2015 at 3:36 pm

    Thanks for your article

    So you mean that we should keep using HttpFoundation for existing project?

    And what about the future? Is PSR-7 system will be the default used system on Symfony instead of HttpFoundation? If not, why?

    Regards.

    Reply
    1. Kévin Dunglas says:
      June 4, 2015 at 3:49 pm

      For now, the PSR-7 bridge should be used only when dealing with libraries and middlewares supporting (only) PSR-7 messages.

      It’s the case for Symfony 2 and 3. For Symfony 4, maybe that HttpFoundation will be refactored (with BC break) to be natively compliant with PSR-7.

      Reply
      1. Sullivan SENECHAL says:
        June 4, 2015 at 4:01 pm

        Nice to hear that. Symfony still has many years in front of him! 😉

        Thanks for reply.

        Reply
  2. Antonio J. García Lagar says:
    June 18, 2015 at 8:27 am

    Thanks for your work with the PSR-7 bridge.

    Just a note. The Zend Diactoros project finally dropped the minimum PHP version requirement to 5.4 three days after you wrote this article: https://github.com/zendframework/zend-diactoros/commit/8dd06b6c9d40d85d3e92f490863a0295f7a50a74

    Reply
  3. Hari K T says:
    June 21, 2015 at 5:41 pm

    Thank you for the article.

    I have a doubt, how the bridge will help to make use of the psr-7 middleware approach. Do you have any examples for the same ?

    I am taking some code which I was looking to figure out . This is the app.php code .

    $kernel = new AppKernel(‘prod’, false);
    $kernel->loadClassCache();

    $request = Request::createFromGlobals();
    $response = $kernel->handle($request);
    $response->send();
    $kernel->terminate($request, $response);

    What I could understand is the we may not need to make use of the two lines

    $response->send();
    $kernel->terminate($request, $response);

    But instead convert to PSR-7 response and use in the middleware ?

    Thank you.

    Reply
  4. Pingback: Talk à propos de PSR-7 et Symfony ce jeudi à Lille - expert Symfony et e-commerce - Lille
  5. Pingback: DunglasActionBundle: Symfony controllers, redesigned - expert Symfony et e-commerce - Lille
  6. Beno!t ♫ (@bpolaszek) says:
    August 30, 2018 at 11:53 am

    For people coming here, who want to type-hint ServerRequestInterface in controllers on Symfony 4, please note you have to composer req sensio/framework-extra-bundle for it to work.

    Reply
    1. Beno!t ♫ (@bpolaszek) says:
      September 27, 2018 at 10:21 am

      And composer req zendframework/zend-diactoros, too.

      Reply

Leave a ReplyCancel reply

Social

  • Bluesky
  • GitHub
  • LinkedIn
  • Mastodon
  • X
  • YouTube

Links

  • API Platform
  • FrankenPHP
  • Les-Tilleuls.coop
  • Mercure.rocks
  • Vulcain.rocks

Subscribe to this blog

Top Posts & Pages

  • JSON Columns and Doctrine DBAL 3 Upgrade
  • Securely Access Private Git Repositories and Composer Packages in Docker Builds
  • Preventing CORS Preflight Requests Using Content Negotiation
  • FrankenPHP: The Modern Php App Server, written in Go
  • Symfony's New Native Docker Support (Symfony World)
  • Develop Faster With FrankenPHP
  • PHP and Symfony Apps As Standalone Binaries
  • How to debug Xdebug... or any other weird bug in PHP
  • HTTP compression in PHP (new Symfony AssetMapper feature)
  • Generate a Symfony password hash from the command line

Tags

Apache API API Platform Buzz Caddy Docker Doctrine FrankenPHP Go Google GraphQL HTTP/2 Hydra hypermedia Hébergement Javascript JSON-LD Kubernetes La Coopérative des Tilleuls Les-Tilleuls.coop Lille Linux Mac Mercure Mercure.rocks Messagerie Instantanée MySQL performance PHP Punk Rock Python React REST Rock'n'Roll Schema.org Security SEO SEO Symfony Symfony Live Sécurité Ubuntu Web 2.0 webperf XML

Archives

Categories

  • DevOps (84)
    • Ubuntu (68)
  • Go (17)
  • JavaScript (46)
  • Mercure (7)
  • Opinions (91)
  • PHP (170)
    • API Platform (77)
    • FrankenPHP (9)
    • Laravel (1)
    • Symfony (97)
    • Wordpress (6)
  • Python (14)
  • Security (15)
  • SEO (25)
  • Talks (46)
© 2025 Kévin Dunglas | Powered by Minimalist Blog WordPress Theme