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:
class DefaultController extends Controller
public function indexAction(ServerRequestInterface $request)
// Interact with the PSR-7 request
$response = new Response();
// Interact with the PSR-7 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