PSR-7: HTTP Messages Today

by Mateusz Tymek — on PHP

PSR-7 is here and is big. Now, more than one month after it was voted, a lot of work has been put into projects supporting this standard. Even though we’re still at the beginning of this great journey, it is exciting to see what is already available, thanks to great work of PHP community.

Watching related projects since the inception of that standard, I will present packages that can serve as foundation for actual applications: HTTP message implementations, dispatchers and micro frameworks.

What is PSR-7?

If you don't know about PSR-7, now it's the right time to learn it! It defines a common standard for HTTP request and response representation in PHP. Why is it important? It's all about finding a common language between PHP libraries that do something with HTTP. Imagine being able to build your application using ANY libraries that are convenient to you: take authentication from Symfony 2, router from Aura, combine them with MVC from Zend Framework and all of them should play nicely with each other. You won't be locked with any full-stack solution, you can pick any component that works well for you.

If you are new to PSR-7, be sure to read this and this.

Official spec is available here.

PSR-7 implementations

Following libraries implement interfaces declared in psr/http-message (official PSR-7 package). They are replaceable - you can pick an implementation that is most handy for you and use it together with any PSR-7 framework.

zend-diactoros

Interesting name, isn't it? Took me a while to remember the spelling, but it provides great, complete implementation of PSR-7 messages.
Authored by the boss of Zend Framework - Matthew Weier O'Phinney. Initially developed as a proof-of-concept PSR-7 implementation, it evolved together with the standard to become full-featured, production-ready package.
Besides interface implementations, currently it supports serialization (creating messages from string and vice versa) and comes with handy classes for building HTTP responses.

guzzlehttp/psr7

Written by folks behind Guzzle, the most advanced HTTP client library written in PHP.
It's a PSR-7 library for building HTTP clients, at this moment it is missing ServerRequestInterface and UploadedFileInterface implementations (although PR implementing them are welcome by authors). It comes with interesting stream implementations: CachingStream for seeking on non-seekable streams, InflateStream for compressed data and so on. It also comes functional interface that allows (de)serialization, filtering, working with URIs and more.

PSR-7 Dispatchers

PSR-7 dispatcher is a library that can execute stack of middleware. In order to build your application on top of dispatcher, you'll need to add elements like dynamic router and IoC container yourself. This is great if you need flexibility, but if you are building something generic, you may want to start with microframework instead.

zendframework/zend-stratigility

Explained as "a port of Sencha Connect (https://github.com/senchalabs/connect) to PHP", which doesn't say much about what it actually is.
Personally, I would define Stratigility as a middleware dispatcher combined with with static router. Still not clear? See what it can do:

  • it can work as a router for simple set of static pages:

    $app->pipe('/about-us', function (ServerRequestInterface $request, ResponseInterface $response) {
        $response->getBody()->write('<h1>About us</h1>');
        return $response;
    });
    $app->pipe('/company', /* ... */);
    $app->pipe('/', /* ... */);
  • it can be used to funnel traffic between different PSR-7 compatible frameworks (or bridge middleware, if you want to connect with ZF1 for instance):

    $app->pipe('/user', $zf3Middleware);
    $app->pipe('/api', $apigilityMiddleware);
    $app->pipe('/home', $slimMiddleware);
    $app->pipe('/test', function (ServerRequestInterface $request, ResponseInterface $response) {
        $response->getBody()->write('Hello, world!');
        return $response;
    });
  • finally, with help of zend-stratigility-dispatch (still under development), it can act as a micro framework (see skeleton app)

relay/relay

Another dispatcher, Relay, comes with interesting idea of "resolvers", allowing to dynamically instantiate middleware. This is simple but powerful - you can link it with your own Dependency Injection system, without using non-official container-interop standard.

Microframeworks

Microframeworks here share the same base with dispatchers, adding libraries that you'll need for almost every web project now: router and (usually) IoC container.

slim/slim

Well known micro framework star, Slim is based on PSR-7 since version 3 (still in development). Compared with other projects explained here, Slim is a complex beast: supports sessions, HTTP cache, event dispatcher... it can do quite a lot for you before you'll need to install anything else.

radar/project

Radar works as PSR-7 framework for applications designed according to ADR (Action-Domain-Responder) pattern defined by Paul M. Jones.
Based on middleware dispatcher, with Aura.Router for routing and Aura.Di for IoC container, Radar is a great base to experiment with ADR pattern.

woohoolabs/harmony

Another new player, Harmony, attempts to create an "invisible framework", based on philosophy described in Phil Sturgeon's article. Harmony's author wants to create a minimal framework on top of low-weight, replaceable components like router and service container. At this moment it combines dispatcher with container-interop connector (container can be injected into middleware). Router is replaceable, defaults to FastRoute from Nikita Popov.
Harmony's idea is to start with just this elements and plug in anything else you need via composer.

PSR-7 support in full-stack frameworks

So far only Symfony and Laravel (as it is based on SF's HTTP) are directly supporting PSR-7 messages defined in standard ("directly" meaning that out of the box you can write controllers accepting ServerRequestInterface and returning ResponseInterface). PSR-7 support was added to current major versions, without a BC-break.
Zend Framework is going to support PSR-7 natively from version 3.0, although it is very likely that we will see a bridge, or at least middleware for zend-stratigility a bit earlier.

Summary

Last few weeks have been really exciting: imagine all those smart community gurus working together on common standard and then on code based on it. Future looks bright for PHP, I cannot wait to see how PSR-7 will be used in future projects!


comments powered by Disqus