Develop web APIs in PHP
using middleware with Expressive

by Enrico Zimuel
Senior Software Engineer
Zend, a Rogue Wave Company (USA)

Code Europe, Warsaw, 24th April 2018

About me


  • PHP: Hypertext Preprocessor
  • The most popular server-side language: PHP is used by 83% of all the websites (source:
  • Used by Facebook, Wikipedia, Yahoo, Etsy, Flickr, Digg, etc
  • 23 years of usage, since 1995
  • Full OOP support since PHP 5


Released: 3 December 2015

Previous major was PHP 5, 13 July 2004

Skipped PHP 6: Unicode failure

Last release is 7.2.4 (29 March 2018)

PHP 7 performance

PHP 7 is also faster than Python 3!


	$a = [];
	for ($i = 0; $i < 1000000; $i++) {
	  $a[$i] = ["hello"];
PHP 5.6 PHP 7
Memory Usage 428 MB 33 MB
Execution time 0.49 sec 0.06 sec

From 7.0 to 7.2

PHP 7.2 is 20% faster than 7.0 and 10% faster than 7.1 (source)

Moving to PHP 7

  • Badoo saved one million dollars switching to PHP 7 (source)
  • Tumblr reduced the latency and CPU load by half moving to PHP 7 (source)
  • Dailymotion handles twice more traffic with same infrastructure switching to PHP 7 (source)

PHP 7 is not only fast!

  • Return and Scalar Type Declarations
  • Improved Exception hierarchy
  • Many fatal errors converted to Exceptions
  • Secure random number generator
  • Authenticated encryption AEAD (PHP 7.1+)
  • Nullable types (PHP 7.1+)
  • Argon2 for secure password storage
  • and more!

Web APIs in PHP



HTTP Request:

	GET /api/version

HTTP Response:

	HTTP/1.1 200 OK
	Connection: close
	Content-Length: 17
	Content-Type: application/json

	  "version": "1.0"


A function that gets a request and generates a response

	function ($request)
	    // do something with $request
	    return $response;

Delegating middleware

	function ($request, $delegate)
	    // delegating $request to another middleware
	    $response = $delegate($request);
	    return $response;

Example: cache

	function ($request, $delegate) use ($cache)
	    if ($cache->has($request)) {
	        return $cache->get($request);
	    $response = $delegate($request);
	    $cache->set($request, $response);
	    return $response;


  • PHP Framework Interop Group (PHP FIG)
  • A working group for defining common standards to interop between PHP frameworks/libraries
  • PHP Standards Recommendations (PSR)
  • More information at


Common interfaces for representing HTTP messages as described in RFC 7230 and RFC 7231, and URIs for use with HTTP messages as described in RFC 3986


	use Psr\Http\Message\ResponseInterface; // PSR-7
	use Psr\Http\Message\ServerRequestInterface; // PSR-7
	use Zend\Diactoros\Response\JsonResponse;

	function (ServerRequestInterface $request): ResponseInterface
	    $name = $request->getAttribute('name', 'Mr. Robot');
	    return new JsonResponse(['hello' => $name]);

e.g. GET /api/hello[/{name}]


Common interfaces for HTTP server request handlers and HTTP server middleware components that use HTTP messages as described by PSR-7

PSR-15: Handler

	namespace Psr\Http\Server;

	use Psr\Http\Message\ResponseInterface;
	use Psr\Http\Message\ServerRequestInterface;

	interface RequestHandlerInterface
	    public function handle(
	        ServerRequestInterface $request
	    ): ResponseInterface;

An handler returns a response, without delegate

PSR-15: Middleware

	namespace Psr\Http\Server;

	use Psr\Http\Message\ResponseInterface;
	use Psr\Http\Message\ServerRequestInterface;

	interface MiddlewareInterface
	    public function process(
	        ServerRequestInterface $request,
	        RequestHandlerInterface $handler
	    ): ResponseInterface;

A middleware participates in processing an HTTP message, it may deletegate.

Expressive 3.0

The PHP framework for middleware applications

  • PSR-7 support (using zend-diactoros)
  • PSR-15 support
  • Piping workflow (using zend-stratigility)
  • Features: routing, dependency injection, templating, error handling
  • Last release 3.0.6, 16th April 2018


You can install Expressive using composer:

composer create-project zendframework/zend-expressive-skeleton api


	$app->get('/api/ping', function ($request) {
	    return JsonResponse(['ack' => time()])

	// or implement a RequestHandlerInterface
	$app->get('/api/ping', App\Handler\PingHandler::class);


	namespace App\Handler;

	use Psr\Http\Message\ResponseInterface;
	use Psr\Http\Message\ServerRequestInterface;
	use Psr\Http\Server\RequestHandlerInterface;
	use Zend\Diactoros\Response\JsonResponse;

	class PingHandler implements RequestHandlerInterface
	    public function handle(
	        ServerRequestInterface $request
	    ) : ResponseInterface {
	        return new JsonResponse(['ack' => time()]);



Route a REST API

	$app->route('/api/users[/{id}]', [
	], ['GET', 'POST', 'PATCH', 'DELETE'], 'api.users');

	// or route each HTTP method
	$app->get('/api/users[/{id}]', ..., 'api.users.get');
	$app->post('/api/users', ..., '');
	$app->patch('/api/users/{id}', ..., 'api.users.patch');
	$app->delete('/api/users/{id}', ..., 'api.users.delete');

Building a Web API

  • Managing the HTTP request and response
  • Choosing a representation format
  • Choosing an error format
  • Filtering & validating input data
  • Authenticating HTTP requests
  • Authorizing HTTP requests

Tools for Web API

REST example

Run PHP as Node.js

  • Run PHP in async way!
  • Use Swoole or ReactPHP
  • Very useful for web API/microservices
  • Benchmark using Expressive + Swoole: 4x faster than nginx and Apache (source)


More info:

Contact me: enrico.zimuel [at]

Follow me: @ezimuel

Creative Commons License
This work is licensed under a
Creative Commons Attribution-ShareAlike 3.0 Unported License.
I used reveal.js to make this presentation.