DEVELOPINGWEBAPIS USINGMIDDLEWAREINPHP7 by Senior Software Engineer , a Rogue Wave Company (USA) , Turin, 15th June 2017 Enrico Zimuel Zend ApiConf
ABOUTME Developer since 1996 Senior Software Engineer at , a Company Core team of and and international speaker Research Programmer at Author of and Co-founder of Zend Rogue Wave Apigility ZF TEDx UvA books articles PUG Torino
PHP PHP: Hypertext Preprocessor The most popular server-side language: PHP is used by 82.6% of all the websites (source: ) Used by Facebook, Wikipedia, Yahoo, Etsy, Flickr, Digg, etc 22 years of usage, since 1995 Full OOP support since PHP 5 w3techs.com
PHP7 Released: 3 December 2015 Previous major was , 13 July 2004PHP 5 Skipped PHP 6: Unicode failure Last release is (8 Jun 2017)7.1.6
PHP7PERFORMANCE PHP 7 is also faster than !Python 3
BENCHMARK $a = []; for ($i = 0; $i < 1000000; $i++) { $a[$i] = ["hello"]; } echo memory_get_usage(true); PHP 5.6 PHP 7 Memory Usage 428 MB 33 MB Execution time 0.49 sec 0.06 sec
MOVINGTOPHP7 Badoo saved one million dollars switching to PHP 7 ( ) Tumblr reduced the latency and CPU load by half moving to PHP 7 ( ) Dailymotion handles twice more tra c with same infrastructure switching to PHP 7 ( ) source source source
PHP7ISNOTONLYFAST! 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+) and !more
WEBAPISINPHP7
HTTPIN/OUT
EXAMPLE Request: GET /api/version Response: HTTP/1.1 200 OK Connection: close Content-Length: 17 Content-Type: application/json { "version": "1.0" }
MIDDLEWARE A function that gets a request and generates a response use PsrHttpMessageServerRequestInterface as Request; use InteropHttpServerMiddlewareDelegateInterface; function (Request $request, DelegateInterface $next) { // doing something with $request... // for instance calling the delegate middleware $next $response = $next->process($request); // manipulate the $response return $response; } This is called lambda middleware.
DELEGATEINTERFACE namespace InteropHttpServerMiddleware; use PsrHttpMessageResponseInterface; use PsrHttpMessageServerRequestInterface; interface DelegateInterface { /** * @return ResponseInterface; */ public function process(ServerRequestInterface $request); } DelegateInterface is part of HTTP Middleware proposalPSR-15
EXPRESSIVE2.0 The PHP framework for Middleware applications PSR-7 HTTP Message support (using ) Support of lambda middleware (PSR-15) and double pass ($request, $response, $next) Piping work ow (using ) Features: routing, dependency injection, templating, error handling Last release 2.0.3, 28th March 2017 zend-diactoros zend-stratigility
INSTALLATION You can install Expressive 2.0 using :composer composer create-project zendframework/zend-expressive-skeleton api Choose the default options during the installation
DEFAULT The skeleton has 2 URL as example: / and /api/ping The routes are registered in /con g/routes.php The middleware actions are stored in /src/App/Action
ROUTES $app->get('/', AppActionHomePageAction::class, 'home'); $app->get('/api/ping', AppActionPingAction::class, 'api.ping'); /con g/routes.php
APIMIDDLEWARE namespace AppAction; use InteropHttpServerMiddlewareDelegateInterface; use InteropHttpServerMiddlewareMiddlewareInterface; use ZendDiactorosResponseJsonResponse; use PsrHttpMessageServerRequestInterface; class PingAction implements MiddlewareInterface { public function process( ServerRequestInterface $request, DelegateInterface $delegate ) { return new JsonResponse(['ack' => time()]); } } /src/App/Action/PingAction.php
PIPELINEWORKFLOW $app->pipe(ErrorHandler::class); $app->pipe(ServerUrlMiddleware::class); $app->pipeRoutingMiddleware(); $app->pipe(ImplicitHeadMiddleware::class); $app->pipe(ImplicitOptionsMiddleware::class); $app->pipe(UrlHelperMiddleware::class); $app->pipeDispatchMiddleware(); $app->pipe(NotFoundHandler::class); /con g/pipeline.php
SERVICECONTAINER use ZendServiceManagerConfig; use ZendServiceManagerServiceManager; $config = require __DIR__ . '/config.php'; $container = new ServiceManager(); $config = new Config($config['dependencies']); $config->configureServiceManager($container); $container->setService('config', $config); return $container; /con g/container.php
THEEXPRESSIVEAPP chdir(dirname(__DIR__)); require 'vendor/autoload.php'; call_user_func(function () { $container = require 'config/container.php'; $app = $container->get(ZendExpressiveApplication::class); require 'config/pipeline.php'; require 'config/routes.php'; $app->run(); }); /public/index.php
ROUTEARESTAPI $app->route('/api/users[/{user-id}]', [ AuthenticationAuthenticationMiddleware::class, AuthorizationAuthorizationMiddleware::class, ApiActionUserAction::class ], ['GET', 'POST', 'PATCH', 'DELETE'], 'api.users'); // or route each HTTP method $app->get('/api/users[/{user-id}]', ..., 'api.users.get'); $app->post('/api/users', ..., 'api.users.post'); $app->patch('/api/users/{user-id}', ..., 'api.users.patch'); $app->delete('/api/users/{user-id}', ..., 'api.users.delete');
RESTDISPATCHTRAIT use PsrHttpMessageServerRequestInterface; use InteropHttpServerMiddlewareDelegateInterface; trait RestDispatchTrait { public function process( ServerRequestInterface $request, DelegateInterface $delegate ) { $method = strtolower($request->getMethod()); if (method_exists($this, $method)) { return $this->$method($request); } return $response->withStatus(501); // Method not implemented } }
RESTMIDDLEWARE class UserAction implements MiddlewareInterface { use RestDispatchTrait; public function get(ServerRequestInterface $request) { $id = $request->getAttribute('user-id', false); $data = (false === $id) ? /* all users */ : /* user id */; return new JsonResponse($data); } public function post(ServerRequestInterface $request){ ... } public function patch(ServerRequestInterface $request){ ... } public function delete(ServerRequestInterface $request){ ... } } ApiActionUserAction.php
THANKS! More info: https://framework.zend.com/blog Contact me: enrico.zimuel [at] roguewave.com Follow me: @ezimuel This work is licensed under a . I used to make this presentation. Creative Commons Attribution-ShareAlike 3.0 Unported License reveal.js

Developing web APIs using middleware in PHP 7