Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Zend/Expressive 3 – The Next Generation

167 views

Published on

After the PSR-15 was finally published in the spring of 2018, the micro framework Zend/Expressive has archieved the next stage with its 3.0 release. Zend/Expressive suits all kinds of applications perfectly: from classic full-stack web applications via REST services through to special applications like PHP-based Alexa Skills. The third version of the micro framework based on Middleware can be your means of choice. This session introduces all the innovations in Zend/Expressive 3, presents different application possibilities, and demonstrates how to migrate from older Zend/Expressive versions.

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Zend/Expressive 3 – The Next Generation

  1. 1. 1 / 70 ZendExpressive 3 The Next Generation
  2. 2. 2 / 70 Ralf Eggert CEO Travello GmbH PHP Developer Alexa Champion
  3. 3. 3 / 70 Some definitions
  4. 4. 4 / 70 PSR PHP Standards Recommendations By the PHP Framework Interop Group https://www.php-fig.org/
  5. 5. 5 / 70 PSR-7 HTTP Message Interface HTTP Request & Response, Streams, Uris, Uploads https://www.php-fig.org/psr/psr-7/
  6. 6. 6 / 70 PSR-11 Container interface Dependency Injection Container https://www.php-fig.org/psr/psr-11/
  7. 7. 7 / 70 PSR-15 HTTP Server Request Handlers Request Handlers & Middleware https://www.php-fig.org/psr/psr-15/
  8. 8. 8 / 70 Some questions
  9. 9. 9 / 70 Question 1: Who is using the Zend Framework in general?
  10. 10. 10 / 70 Question 2: Who is using ZendExpressive in particular? Which version? (1/2/3)
  11. 11. 11 / 70 Question 3: What kind of applications have you built with ZendExpressive so far?
  12. 12. 12 / 70 From ZE1 to ZE3
  13. 13. 13 / 70 28/01/2016 ZE1 Released Focus PSR-7
  14. 14. 14 / 70 28/01/2016 07/03/2017 ZE1 Released Focus PSR-7 ZE2 Released Focus PSR-11
  15. 15. 15 / 70 28/01/2016 07/03/2017 16/03/2018 ZE1 Released Focus PSR-7 ZE2 Released Focus PSR-11 ZE3 Released Focus PSR-15
  16. 16. 16 / 70 28/01/2016 ??/??/201907/03/2017 16/03/2018 ZE1 Released Focus PSR-7 ZE2 Released Focus PSR-11 ZE3 Released Focus PSR-15 ZE4 Released Focus ???
  17. 17. 17 / 70 28/01/2016 07/03/2017 16/03/2018 ZE1 Released Focus PSR-7 ZE2 Released Focus PSR-11 ZE3 Released Focus PSR-15 Just kidding!
  18. 18. 18 / 70 ZendExpressive 1 PSR-7 compatible Middleware based Microframework Support for various router, DI container and template solutions
  19. 19. 19 / 70 ZendExpressive 2 Added PSR-11 support, programmatic pipelines, improved error handling, modular applications and development tooling to the mix.
  20. 20. 20 / 70 ZendExpressive 3 Extended with PSR-15 support, requires PHP 7.1, massive internal refactoring and adds new components for session, CSRF, flash messages, etc.
  21. 21. 21 / 70 ZendExpressive Evolution ZE1 ZE2 ZE3 Development Focus PSR-7 PSR-11 PSR-15 Minimal PHP Version 5.6 or 7.0 5.6 or 7.0 7.1 (7.2 Support) Highlight First release Programmatic pipelines New components
  22. 22. 22 / 70 From Actions to Handlers
  23. 23. 23 / 70 namespace PizzaAction; use PsrHttpMessageResponseInterface; use PsrHttpMessageServerRequestInterface; use PizzaModelRepositoryPizzaRepositoryInterface; class ShowIntroAction { public function __invoke( ServerRequestInterface $request, ResponseInterface $response, callable $next = null ) { $pizzas = $this->pizzaRepository->getPizzas(); return new HtmlResponse( $this->renderer->render( 'pizza::intro', ['pizzas' => $pizzas] ) ); } } ZE1
  24. 24. 24 / 70 namespace PizzaAction; use InteropHttpServerMiddlewareDelegateInterface; use InteropHttpServerMiddlewareMiddlewareInterface as ServerMiddlewareInterface; use PsrHttpMessageServerRequestInterface; use PizzaModelRepositoryPizzaRepositoryInterface; class ShowIntroAction implements ServerMiddlewareInterface { public function process( ServerRequestInterface $request, DelegateInterface $delegate ) { $pizzas = $this->pizzaRepository->getPizzas(); return new HtmlResponse( $this->renderer->render( 'pizza::intro', ['pizzas' => $pizzas] ) ); } } ZE2
  25. 25. 25 / 70 namespace PizzaAction; use PsrHttpMessageResponseInterface; use PsrHttpMessageServerRequestInterface; use PsrHttpServerRequestHandlerInterface; use PizzaModelRepositoryPizzaRepositoryInterface; class ShowIntroHandler implements RequestHandlerInterface { public function handle( ServerRequestInterface $request ) : ResponseInterface { $pizzas = $this->pizzaRepository->getPizzas(); return new HtmlResponse( $this->renderer->render( 'pizza::intro', ['pizzas' => $pizzas] ) ); } } ZE3
  26. 26. 26 / 70 ZE3 Request Handlers Evolved from ZE1 action classes to ZE3 request handlers Implement PSR-15 interfaces now Easy migration path
  27. 27. 27 / 70 From configurable to programmatic middleware pipelines
  28. 28. 28 / 70 // /config/autoload/middleware-pipeline.php return [ 'middleware_pipeline' => [ 'always' => [ 'middleware' => [ ServerUrlMiddleware::class, ], 'priority' => 10000, ], 'routing' => [ 'middleware' => [ ApplicationFactory::ROUTING_MIDDLEWARE, UrlHelperMiddleware::class, ApplicationFactory::DISPATCH_MIDDLEWARE, ], 'priority' => 1, ], 'error' => [ 'middleware' => [], 'error' => true, 'priority' => -10000, ], ], ]; ZE1
  29. 29. 29 / 70 // /config/pipeline.php $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); ZE2
  30. 30. 30 / 70 // /config/pipeline.php return function ( Application $app, MiddlewareFactory $factory, ContainerInterface $container ) : void { $app->pipe(ErrorHandler::class); $app->pipe(ServerUrlMiddleware::class); $app->pipe(RouteMiddleware::class); $app->pipe(ImplicitHeadMiddleware::class); $app->pipe(ImplicitOptionsMiddleware::class); $app->pipe(MethodNotAllowedMiddleware::class); $app->pipe(UrlHelperMiddleware::class); $app->pipe(DispatchMiddleware::class); $app->pipe(NotFoundHandler::class); }; ZE3
  31. 31. 31 / 70 // /module/Application/src/Config/PipelineDelegatorFactory.php namespace ApplicationConfig; class PipelineDelegatorFactory implements DelegatorFactoryInterface { public function __invoke( ContainerInterface $container, $name, callable $callback, array $options = null ) { $application = $callback(); $application->pipe(ErrorHandler::class); $application->pipe(ServerUrlMiddleware::class); $application->pipe(RouteMiddleware::class); $application->pipe(ImplicitHeadMiddleware::class); $application->pipe(ImplicitOptionsMiddleware::class); $application->pipe(MethodNotAllowedMiddleware::class); $application->pipe(UrlHelperMiddleware::class); $application->pipe(DispatchMiddleware::class); $application->pipe(NotFoundHandler::class); return $application; } }; ZE3
  32. 32. 32 / 70 ZE3 Middleware Pipeline Evolved from configuration arrays to delegator factory classes Medium migration path
  33. 33. 33 / 70 Evolving of the pipeline middleware
  34. 34. 34 / 70 namespace ZendExpressiveHelper; use PsrHttpMessageResponseInterface; use PsrHttpMessageServerRequestInterface; use ZendExpressiveRouterRouteResult; class UrlHelperMiddleware { public function __invoke( ServerRequestInterface $request, ResponseInterface $response, callable $next ) { $result = $request->getAttribute(RouteResult::class, false); if ($result instanceof RouteResult) { $this->helper->setRouteResult($result); } return $next($request, $response); } } ZE1
  35. 35. 35 / 70 namespace ZendExpressiveHelper; use InteropHttpServerMiddlewareDelegateInterface; use InteropHttpServerMiddlewareMiddlewareInterface as ServerMiddlewareInterface; use PsrHttpMessageServerRequestInterface; use ZendExpressiveRouterRouteResult; class UrlHelperMiddleware implements ServerMiddlewareInterface { public function process( ServerRequestInterface $request, DelegateInterface $delegate ) { $result = $request->getAttribute(RouteResult::class, false); if ($result instanceof RouteResult) { $this->helper->setRouteResult($result); } return $delegate->process($request); } } ZE2
  36. 36. 36 / 70 namespace ZendExpressiveHelper; use PsrHttpMessageResponseInterface; use PsrHttpMessageServerRequestInterface; use PsrHttpServerMiddlewareInterface; use PsrHttpServerRequestHandlerInterface; use ZendExpressiveRouterRouteResult; class UrlHelperMiddleware implements MiddlewareInterface { public function process( ServerRequestInterface $request, RequestHandlerInterface $handler ) : ResponseInterface { $result = $request->getAttribute(RouteResult::class, false); if ($result instanceof RouteResult) { $this->helper->setRouteResult($result); } return $handler->handle($request); } } ZE3
  37. 37. 37 / 70 ZE3 Pipeline Middleware Evolved to full PSR-15 interface implementation Easy migration path
  38. 38. 38 / 70 Evolving of the front controller
  39. 39. 39 / 70 if (php_sapi_name() === 'cli-server' && is_file(__DIR__ . parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)) ) { return false; } chdir(dirname(__DIR__)); require 'vendor/autoload.php'; /** @var InteropContainerContainerInterface $container */ $container = require 'config/container.php'; /** @var ZendExpressiveApplication $app */ $app = $container->get(ZendExpressiveApplication::class); $app->run(); ZE1
  40. 40. 40 / 70 if (PHP_SAPI === 'cli-server' && $_SERVER['SCRIPT_FILENAME'] !== __FILE__) { return false; } chdir(dirname(__DIR__)); require 'vendor/autoload.php'; call_user_func(function () { /** @var PsrContainerContainerInterface $container */ $container = require 'config/container.php'; /** @var ZendExpressiveApplication $app */ $app = $container->get(ZendExpressiveApplication::class); require 'config/pipeline.php'; require 'config/routes.php'; $app->run(); }); ZE2
  41. 41. 41 / 70 if (PHP_SAPI === 'cli-server' && $_SERVER['SCRIPT_FILENAME'] !== __FILE__) { return false; } chdir(dirname(__DIR__)); require 'vendor/autoload.php'; (function () { /** @var PsrContainerContainerInterface $container */ $container = require 'config/container.php'; /** @var ZendExpressiveApplication $app */ $app = $container->get(ZendExpressiveApplication::class); $factory = $container->get(ZendExpressiveMiddlewareFactory::class); (require 'config/pipeline.php')($app, $factory, $container); (require 'config/routes.php')($app, $factory, $container); $app->run(); })(); ZE3
  42. 42. 42 / 70 ZE3 Front Controller From polluting the global namespace to self-called anonymous function with its own scope Easy migration path
  43. 43. 43 / 70 New ZE3 components
  44. 44. 44 / 70 Authentication Middleware for Authentication with Basic Auth, OAuth2, Session and ZendAuthentication
  45. 45. 45 / 70 Authorization Middleware for Authorization with adapters for both RBAC and ACL authorization
  46. 46. 46 / 70 Session Middleware with PSR-7 support, lazy sessions and ext-session extension
  47. 47. 47 / 70 CSRF Middleware and guards for Cross-Site Request Forgery (CSRF) protection
  48. 48. 48 / 70 Flash Messages Middleware and support for Flash Messages
  49. 49. 49 / 70 HttpHandlerRunner Utilities emitting PSR-7 responses and running PSR-15 server request handlers
  50. 50. 50 / 70 Swoole Expressive support for Swoole, the PHP asynchronous programming framework
  51. 51. 51 / 70 HAL JSON Expressive support for Hypertext Application Language (used by Apigility)
  52. 52. 52 / 70 Problem details Expressive support for problem details format (used by Apigility)
  53. 53. 53 / 70 Components More than 30 components and helper repositories for the ZendExpressive cosmos so far And don't forget the other Zend Framework components
  54. 54. 54 / 70 Applications
  55. 55. 55 / 70 Applications Which kind of applications can be build with ZendExpressive?
  56. 56. 56 / 70 Applications Classical websites
  57. 57. 57 / 70 Applications Backends
  58. 58. 58 / 70 Applications RESTful APIs
  59. 59. 59 / 70 Applications Alexa Skills
  60. 60. 60 / 70 phlexa PHP Framework to build voice applications for Amazon Alexa (built with ZE3) https://www.phoice.tech/phlexa
  61. 61. 61 / 70 Applications So many opportunities! What are you planning to build next?
  62. 62. 62 / 70 Migration to ZE3
  63. 63. 63 / 70 Migration to ZE3 Migrate your actions to handlers (PSR-15 interfaces)
  64. 64. 64 / 70 Migration to ZE3 Migrate to programmatic middleware pipeline and maybe even introduce a delegator factory
  65. 65. 65 / 70 Migration to ZE3 Migrate your pipeline middleware classes (PSR-15 interfaces)
  66. 66. 66 / 70 Migration to ZE3 Check your current front controller
  67. 67. 67 / 70 Migration to ZE3 Start using the new Expressive components
  68. 68. 68 / 70 Conclusion
  69. 69. 69 / 70 ZendExpressive 3 The Next Generation is ready to start!
  70. 70. 70 / 70 Thanks! ralf@travello.de https://www.travello.de

×