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.

Kicking off with Zend Expressive and Doctrine ORM (PHP South Africa 2018)

495 views

Published on

You've heard of Zend's new framework, Expressive, and you've heard it's the new hotness. In this talk, I will introduce the concepts of Expressive, how to bootstrap a simple application with the framework using best practices, and finally how to integrate a third party tool like Doctrine ORM.

Published in: Technology
  • DOWNLOAD THIS BOOKS INTO AVAILABLE FORMAT (2019 Update) ......................................................................................................................... ......................................................................................................................... Download Full PDF EBOOK here { https://soo.gd/irt2 } ......................................................................................................................... Download Full EPUB Ebook here { https://soo.gd/irt2 } ......................................................................................................................... Download Full doc Ebook here { https://soo.gd/irt2 } ......................................................................................................................... Download PDF EBOOK here { https://soo.gd/irt2 } ......................................................................................................................... Download EPUB Ebook here { https://soo.gd/irt2 } ......................................................................................................................... Download doc Ebook here { https://soo.gd/irt2 } ......................................................................................................................... ......................................................................................................................... ................................................................................................................................... eBook is an electronic version of a traditional print book THIS can be read by using a personal computer or by using an eBook reader. (An eBook reader can be a software application for use on a computer such as Microsoft's free Reader application, or a book-sized computer THIS is used solely as a reading device such as Nuvomedia's Rocket eBook.) Users can purchase an eBook on diskette or CD, but the most popular method of getting an eBook is to purchase a downloadable file of the eBook (or other reading material) from a Web site (such as Barnes and Noble) to be read from the user's computer or reading device. Generally, an eBook can be downloaded in five minutes or less ......................................................................................................................... .............. Browse by Genre Available eBooks .............................................................................................................................. Art, Biography, Business, Chick Lit, Children's, Christian, Classics, Comics, Contemporary, Cookbooks, Manga, Memoir, Music, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance, Science, Science Fiction, Self Help, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult, Crime, Ebooks, Fantasy, Fiction, Graphic Novels, Historical Fiction, History, Horror, Humor And Comedy, ......................................................................................................................... ......................................................................................................................... .....BEST SELLER FOR EBOOK RECOMMEND............................................................. ......................................................................................................................... Blowout: Corrupted Democracy, Rogue State Russia, and the Richest, Most Destructive Industry on Earth,-- The Ride of a Lifetime: Lessons Learned from 15 Years as CEO of the Walt Disney Company,-- Call Sign Chaos: Learning to Lead,-- StrengthsFinder 2.0,-- Stillness Is the Key,-- She Said: Breaking the Sexual Harassment Story THIS Helped Ignite a Movement,-- Atomic Habits: An Easy & Proven Way to Build Good Habits & Break Bad Ones,-- Everything Is Figureoutable,-- What It Takes: Lessons in the Pursuit of Excellence,-- Rich Dad Poor Dad: What the Rich Teach Their Kids About Money THIS the Poor and Middle Class Do Not!,-- The Total Money Makeover: Classic Edition: A Proven Plan for Financial Fitness,-- Shut Up and Listen!: Hard Business Truths THIS Will Help You Succeed, ......................................................................................................................... .........................................................................................................................
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Kicking off with Zend Expressive and Doctrine ORM (PHP South Africa 2018)

  1. 1. @asgrim Kicking off with Zend Expressive and Doctrine ORM James Titcumb PHP South Africa 2018 Follow along (optional): https://github.com/asgrim/book-library
  2. 2. $ whoami James Titcumb www.jamestitcumb.com www.roave.com @asgrim Follow along (optional): https://github.com/asgrim/book-library
  3. 3. @asgrim What is Zend Expressive?
  4. 4. @asgrim Layers of an Expressive application Expressive Stratigility Diactoros PSR-7 Interface DIRouter Template Your Application
  5. 5. @asgrim Layers of an Expressive application Expressive Stratigility Diactoros PSR-7 Interface DIRouter Template Your Application
  6. 6. @asgrim PSR-7 HTTP Message Interfaces
  7. 7. @asgrim HTTP Request POST /talk HTTP/1.1 Host: phpminds.org foo=bar&baz=bat
  8. 8. @asgrim HTTP Response HTTP/1.1 200 OK Content-Type: text/plain This is the response body
  9. 9. @asgrim Layers of an Expressive application Expressive Stratigility Diactoros PSR-7 Interface DIRouter Template Your Application
  10. 10. @asgrim Zend Diactoros PSR-7 implementation
  11. 11. @asgrim Node http.Server using Diactoros $server = ZendDiactorosServer::createServer( function ($request, $response, $done) { return $response->getBody()->write('hello world'); }, $_SERVER, $_GET, $_POST, $_COOKIE, $_FILES ); $server->listen();
  12. 12. @asgrim Layers of an Expressive application Expressive Stratigility Diactoros PSR-7 Interface DIRouter Template Your Application
  13. 13. @asgrim Zend Stratigility Creating & dispatching middleware pipelines
  14. 14. @asgrim So what is “middleware”?
  15. 15. @asgrim Middleware in the middle function(Request $request, RequestHandler $handler) : Response { // ... some code before ... $response = $handler->handle($request); // ... some code after ... return $response; }
  16. 16. @asgrim Some people call it an onion SessionInitialisingMiddleware AuthenticationMiddleware ThingyMiddleware DashboardHandler
  17. 17. @asgrim Some people call it an onion SessionInitialisingMiddleware AuthenticationMiddleware ThingyMiddleware DashboardHandler
  18. 18. @asgrim Some people call it an onion SessionInitialisingMiddleware AuthenticationMiddleware ThingyMiddleware DashboardHandler
  19. 19. @asgrim psr/http-server-middleware
  20. 20. @asgrim Middleware using MiddlewareInterface <?php declare(strict_types=1); namespace AppMiddleware; use PsrHttpMessageResponseInterface; use PsrHttpMessageServerRequestInterface; use PsrHttpServerMiddlewareInterface; use PsrHttpServerRequestHandlerInterface; final class MyMiddleware implements MiddlewareInterface { public function process( ServerRequestInterface $request, RequestHandlerInterface $requestHandler ) : ResponseInterface { return $requestHandler>handle($request); } }
  21. 21. @asgrim Double-pass middleware public function __invoke( Request $request, Response $response, callable $next ): Response { return $next($request, $response); } !!! DEPRECATED !!!
  22. 22. @asgrim Modifying the response function(Request $request, RequestHandler $handler) : Response { $response = $handler->handle($request); return $response->withHeader( 'X-Clacks-Overhead', 'GNU Terry Pratchett' ); }
  23. 23. @asgrim Pipe all the things! $pipe = new ZendStratigilityMiddlewarePipe(); $pipe->pipe($logUncaughtErrorsMiddleware); $pipe->pipe($sessionInitialisingMiddleware); $pipe->pipe($authenticationMiddleware); $pipe->pipe('/', $indexHandlerMiddleware); $pipe->pipe(new NotFoundHandler(...));
  24. 24. @asgrim LogErrorsCaughtMiddleware function(Request $request, RequestHandler $handler) : Response { try { return $handler->handle($request); } catch (Throwable $throwable) { // Log the error, handle it with error page etc. return new JsonResponse( [ 'message' => $throwable->getMessage(), ], 500 ); } }
  25. 25. @asgrim SessionInitialisingMiddleware function(Request $request, RequestHandler $handler) : Response { session_start(); return $handler->handle($request); }
  26. 26. @asgrim function(Request $request, RequestHandler $handler) : Response { if (!$this->doSomeOAuthCheck($request)) { return new JsonResponse( [ 'message' => 'Invalid OAuth token', ], 403 ); } return $handler->handle($request); } AuthenticationMiddleware
  27. 27. @asgrim IndexHandlerMiddleware function(Request $request, RequestHandler $handler) : Response { // ... some code ... return new JsonResponse($someData, 200); }
  28. 28. @asgrim Layers of an Expressive application Expressive Stratigility Diactoros PSR-7 Interface DIRouter Template Your Application
  29. 29. @asgrim Zend Expressive One Ring to bring them all and in the darkness bind them.
  30. 30. @asgrim Routing
  31. 31. @asgrim container-interop
  32. 32. @asgrim Optionally, templating
  33. 33. @asgrim Piping and Routing
  34. 34. @asgrim Zend Framework 2/3 What of them?
  35. 35. @asgrim Middleware vs MVC
  36. 36. @asgrim Using ZF components in Expressive
  37. 37. @asgrim ZF’s Module.php class Module { public function getConfig() { return include __DIR__ . '/../config/module.config.php'; } }
  38. 38. @asgrim ConfigProvider
  39. 39. @asgrim ConfigProvider namespace ZendForm; class ConfigProvider { public function __invoke() { return [ 'dependencies' => $this->getDependencyConfig(), 'view_helpers' => $this->getViewHelperConfig(), ]; } }
  40. 40. @asgrim ConfigProvider#getDependencyConfig() public function getDependencyConfig() { return [ 'abstract_factories' => [ FormAbstractServiceFactory::class, ], 'aliases' => [ 'ZendFormAnnotationFormAnnotationBuilder' => 'FormAnnotationBuilder', AnnotationAnnotationBuilder::class => 'FormAnnotationBuilder', FormElementManager::class => 'FormElementManager', ], 'factories' => [ 'FormAnnotationBuilder' => AnnotationAnnotationBuilderFactory::class, 'FormElementManager' => FormElementManagerFactory::class, ],
  41. 41. @asgrim ZendForm’s Module.php (for Zend Framework) class Module { public function getConfig() { $provider = new ConfigProvider(); return [ 'service_manager' => $provider->getDependencyConfig(), 'view_helpers' => $provider->getViewHelperConfig(), ]; } }
  42. 42. @asgrim config/config.php <?php $aggregator = new ConfigAggregator([ ZendFormConfigProvider::class, // .. other config ... ], $cacheConfig['config_cache_path']); return $aggregator->getMergedConfig();
  43. 43. @asgrim ConfigAggregator
  44. 44. @asgrim config/config.php $aggregator = new ConfigAggregator([ ZendExpressiveRouterFastRouteRouterConfigProvider::class, ZendHttpHandlerRunnerConfigProvider::class, new ArrayProvider($cacheConfig), ZendExpressiveHelperConfigProvider::class, ZendExpressiveConfigProvider::class, ZendExpressiveRouterConfigProvider::class, AppConfigProvider::class, new PhpFileProvider(realpath(__DIR__) . '/autoload/{{,*.}global,{,*.}local}.php'), new PhpFileProvider(realpath(__DIR__) . '/development.config.php'), ], $cacheConfig['config_cache_path']);
  45. 45. @asgrim Layers of an Expressive application Expressive Stratigility Diactoros PSR-7 Interface DIRouter Template Your Application
  46. 46. @asgrim Getting started with Zend Expressive
  47. 47. @asgrim https://github.com/asgrim/book-library
  48. 48. @asgrim Expressive Skeleton
  49. 49. @asgrim Expressive installer - start composer create-project zendframework/zend-expressive-skeleton:3.0.0-rc1 book-library Installing zendframework/zend-expressive-skeleton (3.0.0rc1) - Installing zendframework/zend-expressive-skeleton (3.0.0rc1): Downloading (100%) Created project in test > ExpressiveInstallerOptionalPackages::install Setting up optional packages Setup data and cache dir Removing installer development dependencie
  50. 50. @asgrim Expressive installer - structure What type of installation would you like? [1] Minimal (no default middleware, templates, or assets; configuration only) [2] Flat (flat source code structure; default selection) [3] Modular (modular source code structure; recommended) Make your selection (2): 2 - Copying src/App/ConfigProvider.php
  51. 51. @asgrim Modular structure zend-config-aggregator
  52. 52. @asgrim Modular structure zend-config-aggregator
  53. 53. @asgrim Flat or Modular?
  54. 54. @asgrim Default modular structure src/ MyModule/ src/ ConfigProvider.php Handler/ Entity/ Middleware/ templates/ test/
  55. 55. @asgrim Expressive installer - container? Which container do you want to use for dependency injection? [1] Aura.Di [2] Pimple [3] zend-servicemanager [4] Auryn [5] Symfony DI Container Make your selection or type a composer package name and version (zend-servicemanager): - Adding package zendframework/zend-servicemanager (^3.3) - Copying config/container.php
  56. 56. @asgrim Expressive installer - router? Which router do you want to use? [1] Aura.Router [2] FastRoute [3] zend-router Make your selection or type a composer package name and version (FastRoute): - Adding package zendframework/zend-expressive-fastroute (^3.0.0alpha1) - Whitelist package zendframework/zend-expressive-fastroute - Copying config/routes.php
  57. 57. @asgrim Expressive installer - template? Which template engine do you want to use? [1] Plates [2] Twig [3] zend-view installs zend-servicemanager [n] None of the above Make your selection or type a composer package name and version (n):
  58. 58. @asgrim Expressive installer - whoops? Which error handler do you want to use during development? [1] Whoops [n] None of the above Make your selection or type a composer package name and version (Whoops): n
  59. 59. @asgrim Expressive installer - run it! $ composer serve > php -S 0.0.0.0:8080 -t public/ public/index.php [Thu Sep 1 20:29:33 2016] 127.0.0.1:48670 [200]: /favicon.ico { "welcome": "Congratulations! You have installed the zend-expressive skeleton application.", "docsUrl": "https://docs.zendframework.com/zend-expressive/" }
  60. 60. @asgrim Create the endpoints
  61. 61. @asgrim Book entity class Book { /** * @var string */ private $id; /** * @var bool */ private $inStock = true; public function __construct() { $this->id = (string)Uuid::uuid4(); }
  62. 62. @asgrim Book entity class Book { /** * @return void * @throws AppEntityExceptionBookNotAvailable */ public function checkOut() { if (!$this->inStock) { throw ExceptionBookNotAvailable::fromBook($this); } $this->inStock = false; }
  63. 63. @asgrim Book entity class Book { /** * @return void * @throws AppEntityExceptionBookAlreadyStocked */ public function checkIn() { if ($this->inStock) { throw ExceptionBookAlreadyStocked::fromBook($this); } $this->inStock = true; }
  64. 64. @asgrim FindBookByUuidInterface interface FindBookByUuidInterface { /** * @param UuidInterface $slug * @return Book * @throws ExceptionBookNotFound */ public function __invoke(UuidInterface $slug): Book; }
  65. 65. @asgrim CheckOutHandler public function process(ServerRequestInterface $request, RequestHandler $handler): JsonResponse { try { $book = $this->findBookByUuid->__invoke(Uuid::fromString($request->getAttribute('id'))); } catch (BookNotFound $bookNotFound) { return new JsonResponse(['info' => $bookNotFound->getMessage()], 404); } try { $book->checkOut(); } catch (BookNotAvailable $bookNotAvailable) { return new JsonResponse(['info' => $bookNotAvailable->getMessage()], 423); } return new JsonResponse([ 'info' => sprintf('You have checked out %s', $book->getId()), ]); }
  66. 66. @asgrim return function ( Application $app, MiddlewareFactory $factory, ContainerInterface $container ): void { $app->pipe(ZendStratigilityMiddlewareErrorHandler::class); $app->pipe(ZendExpressiveRouterMiddlewarePathBasedRoutingMiddleware::class); // Routing $app->pipe(ZendExpressiveRouterMiddlewareDispatchMiddleware::class); // Dispatch $app->pipe(ZendExpressiveHandlerNotFoundHandler::class); }; Define application pipeline - pipeline.php
  67. 67. @asgrim return function ( Application $app, MiddlewareFactory $factory, ContainerInterface $container ): void { $app->get( '/book/{id}/check-out', AppHandlerCheckOutHandler::class, 'check-out' ); $app->get( '/book/{id}/check-in', AppHandlerCheckInHandler::class, 'check-in' ); }; Define routes - routes.php
  68. 68. @asgrim Adding some ORM
  69. 69. @asgrim Your application Doctrine quick overview DB DBAL ORM (EntityManager) Entities Finders, Services, ...
  70. 70. @asgrim container-interop-doctrine
  71. 71. @asgrim Installation $ composer require dasprid/container-interop-doctrine Using version ^1.1 for dasprid/container-interop-doctrine ./composer.json has been updated Loading composer repositories with package information Updating dependencies (including require-dev) Package operations: 9 installs, 0 updates, 0 removals - Installing doctrine/lexer (v1.0.1): Loading from cache - Installing doctrine/inflector (v1.3.0): Loading from cache - Installing doctrine/collections (v1.5.0): Loading from cache - Installing doctrine/cache (v1.7.1): Loading from cache - Installing doctrine/annotations (v1.6.0): Loading from cache - Installing doctrine/common (v2.8.1): Loading from cache - Installing doctrine/dbal (v2.6.3): Loading from cache - Installing doctrine/orm (v2.6.1): Loading from cache - Installing dasprid/container-interop-doctrine (1.1.0): Loading from cache Writing lock file Generating autoload files
  72. 72. @asgrim src/App/ConfigProvider.php use DoctrineORMEntityManagerInterface; use ContainerInteropDoctrineEntityManagerFactory; final class ConfigProvider { // ... public function getDependencies() : array { return [ 'factories' => [ EntityManagerInterface::class => EntityManagerFactory::class, // ... other services ], ];
  73. 73. @asgrim 'doctrine' => [ 'connection' => [ 'orm_default' => [ 'driver_class' => PDOPgSqlDriver::class, 'params' => [ 'url' => 'postgres://user:pass@localhost/book_library', ], ], ], 'driver' => [ 'orm_default' => [ 'class' => MappingDriverChain::class, 'drivers' => [ // ... and so on ... config/autoload/doctrine.global.php
  74. 74. @asgrim 'doctrine' => [ 'connection' => [ 'orm_default' => [ 'driver_class' => PDOPgSqlDriver::class, 'params' => [ 'url' => 'postgres://user:pass@localhost/book_library', ], ], ], 'driver' => [ 'orm_default' => [ 'class' => MappingDriverChain::class, 'drivers' => [ // ... and so on ... config/autoload/doctrine.global.php
  75. 75. @asgrim <?php declare(strict_types = 1); use DoctrineORMEntityManagerInterface; use DoctrineORMToolsConsoleHelperEntityManagerHelper; use SymfonyComponentConsoleHelperHelperSet; $container = require __DIR__ . '/container.php'; return new HelperSet([ 'em' => new EntityManagerHelper( $container->get(EntityManagerInterface::class) ), ]); config/cli-config.php
  76. 76. @asgrim Annotating the Entities
  77. 77. @asgrim /** * @ORMEntity * @ORMTable(name="book") */ class Book { /** * @ORMId * @ORMColumn(name="id", type="guid") * @ORMGeneratedValue(strategy="NONE") * @var string */ private $id; src/App/Entity/Book.php
  78. 78. @asgrim /** * @ORMEntity * @ORMTable(name="book") */ class Book { /** * @ORMId * @ORMColumn(name="id", type="guid") * @ORMGeneratedValue(strategy="NONE") * @var string */ private $id; src/App/Entity/Book.php
  79. 79. @asgrim public function __invoke(UuidInterface $id): Book { /** @var Book|null $book */ $book = $this->repository->find((string)$id); if (null === $book) { throw ExceptionBookNotFound::fromUuid($id); } return $book; } src/App/Service/Book/DoctrineFindBookByUuid.php
  80. 80. @asgrim try { $this->entityManager->transactional(function () use ($book) { $book->checkOut(); }); } catch (BookNotAvailable $bookNotAvailable) { return new JsonResponse(['info' => $bookNotAvailable->getMessage()], 423); } src/App/Handler/CheckOutHandler.php
  81. 81. @asgrim Generate the schema $ vendor/bin/doctrine orm:schema-tool:create ATTENTION: This operation should not be executed in a production environment. Creating database schema... Database schema created successfully! $
  82. 82. @asgrim Insert some data INSERT INTO book (id, name, in_stock) VALUES ( '1c06bec9-adae-47c2-b411-73b1db850e6f', 'The Great Escape', true );
  83. 83. @asgrim /book/1c06bec9-adae-47c2-b411-.../check-out {"info":"You have checked out The Great Escape"}
  84. 84. @asgrim /book/1c06bec9-adae-47c2-b411-.../check-in {"info":"You have checked in The Great Escape"}
  85. 85. @asgrim Automatic Flushing Middleware
  86. 86. @asgrim FlushingMiddleware public function process(Request $request, RequestHandler $handler) { $response = $handler->handle($request); if ($this->entityManager->isOpen()) { $this->entityManager->flush(); } return $response; }
  87. 87. @asgrim FlushingMiddleware public function process(Request $request, RequestHandler $handler) { $response = $handler->handle($request); if ($this->entityManager->isOpen()) { $this->entityManager->flush(); } return $response; }
  88. 88. @asgrim FlushingMiddleware public function process(Request $request, RequestHandler $handler) { $response = $handler->handle($request); if ($this->entityManager->isOpen()) { $this->entityManager->flush(); } return $response; }
  89. 89. @asgrim Add to pipeline return function ( Application $app, MiddlewareFactory $factory, ContainerInterface $container ): void { $app->pipe(ZendStratigilityMiddlewareErrorHandler::class); $app->pipe(ZendExpressiveRouterMiddlewarePathBasedRoutingMiddleware::class); // Routing $app->pipe(AppMiddlewareFlushingMiddleware::class); $app->pipe(ZendExpressiveRouterMiddlewareDispatchMiddleware::class); // Dispatch $app->pipe(ZendExpressiveHandlerNotFoundHandler::class); };
  90. 90. @asgrim Doing more with middleware
  91. 91. @asgrim Authentication
  92. 92. @asgrim public function process( ServerRequestInterface $request, RequestHandler $handler ) : Response { $queryParams = $request->getQueryParams(); // DO NOT DO THIS IN REAL LIFE // It's really not secure ;) if (!array_key_exists('authenticated', $queryParams) || $queryParams['authenticated'] !== '1') { return new JsonResponse(['error' => 'You are not authenticated.'], 403); } return $handler->handle($request); } Create the middleware
  93. 93. @asgrim public function process( ServerRequestInterface $request, RequestHandler $handler ) : Response { $queryParams = $request->getQueryParams(); // DO NOT DO THIS IN REAL LIFE // It's really not secure ;) if (!array_key_exists('authenticated', $queryParams) || $queryParams['authenticated'] !== '1') { return new JsonResponse(['error' => 'You are not authenticated.'], 403); } return $handler->handle($request); } Create the middleware
  94. 94. @asgrim public function process( ServerRequestInterface $request, RequestHandler $handler ) : Response { $queryParams = $request->getQueryParams(); // DO NOT DO THIS IN REAL LIFE // It's really not secure ;) if (!array_key_exists('authenticated', $queryParams) || $queryParams['authenticated'] !== '1') { return new JsonResponse(['error' => 'You are not authenticated.'], 403); } return $handler->handle($request); } Create the middleware
  95. 95. @asgrim public function process( ServerRequestInterface $request, RequestHandler $handler ) : Response { $queryParams = $request->getQueryParams(); // DO NOT DO THIS IN REAL LIFE // It's really not secure ;) if (!array_key_exists('authenticated', $queryParams) || $queryParams['authenticated'] !== '1') { return new JsonResponse(['error' => 'You are not authenticated.'], 403); } return $handler->handle($request); } Create the middleware
  96. 96. @asgrim return function ( Application $app, MiddlewareFactory $factory, ContainerInterface $container ): void { $app->pipe(ZendStratigilityMiddlewareErrorHandler::class); $app->pipe(ZendExpressiveRouterMiddlewarePathBasedRoutingMiddleware::class); // Routing $app->pipe(AppMiddlewareFlushingMiddleware::class); $app->pipe(AppMiddlewareAuthenticationMiddleware::class); $app->pipe(ZendExpressiveRouterMiddlewareDispatchMiddleware::class); // Dispatch $app->pipe(ZendExpressiveHandlerNotFoundHandler::class); }; Add middleware to pipe
  97. 97. @asgrim Helios composer require dasprid/helios
  98. 98. @asgrim PSR7-Session composer require psr7-sessions/storageless
  99. 99. @asgrim public function __invoke(ContainerInterface $container, $_, array $_ = null) { $symmetricKey = 'do-not-store-this-key-in-git-store-it-in-configuration-instead-please'; $expirationTime = 1200; // 20 minutes return new SessionMiddleware( new SignerHmacSha256(), $symmetricKey, $symmetricKey, SetCookie::create(SessionMiddleware::DEFAULT_COOKIE) ->withSecure(false) // false on purpose, unless you have https locally ->withHttpOnly(true) ->withPath('/'), new Parser(), $expirationTime, new SystemClock() ); } Factory the middleware
  100. 100. @asgrim return function ( Application $app, MiddlewareFactory $factory, ContainerInterface $container ): void { $app->pipe(ZendStratigilityMiddlewareErrorHandler::class); $app->pipe(ZendExpressiveRouterMiddlewarePathBasedRoutingMiddleware::class); // Routing $app->pipe(AppMiddlewareFlushingMiddleware::class); $app->pipe(PSR7SessionsStoragelessHttpSessionMiddleware::class); $app->pipe(AppMiddlewareAuthenticationMiddleware::class); $app->pipe(ZendExpressiveRouterMiddlewareDispatchMiddleware::class); // Dispatch $app->pipe(ZendExpressiveHandlerNotFoundHandler::class); }; Add middleware to pipe
  101. 101. @asgrim $session = $request->getAttribute(SessionMiddleware::SESSION_ATTRIBUTE); $session->set('counter', $session->get('counter', 0) + 1); Session is stored in Request
  102. 102. @asgrim $skills++;
  103. 103. @asgrim To summarise... ● PSR-7 & PSR-15 lay the foundations! ● Diactoros is just a PSR-7 implementation ● Stratigility is a middleware pipeline: the main bit ● Expressive is a glue for everything ● ConfigProvider is great for aggregating (merging) config ● container-interop-doctrine makes Doctrine work easier ● Middleware all the things! ● Similar concepts in other frameworks (e.g. Slim)
  104. 104. @asgrim Useful references ● https://github.com/asgrim/book-library ● https://framework.zend.com/blog/2017-12-14-expressive-3-dev.html ● https://framework.zend.com/blog/2017-03-13-expressive-2-migration.html ● https://framework.zend.com/blog/2017-03-30-expressive-config-routes.html ● https://mwop.net/blog/2016-05-16-programmatic-expressive.html ● https://docs.zendframework.com/zend-expressive/
  105. 105. Any questions? James Titcumb @asgrim

×