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.
@asgrim
Kicking off with Zend Expressive
and Doctrine ORM
James Titcumb
PHP UK 2017
Who is this guy?
James Titcumb
www.jamestitcumb.com
www.roave.com
www.phphants.co.uk
www.phpsouthcoast.co.uk
@asgrim
@asgrim
What is Zend Expressive?
@asgrim
Layers of an Expressive application
Expressive
Stratigility
Diactoros
PSR-7 Interface
DIRouter Template
Your Appli...
@asgrim
Layers of an Expressive application
Expressive
Stratigility
Diactoros
PSR-7 Interface
DIRouter Template
Your Appli...
@asgrim
PSR-7
HTTP Message Interfaces
@asgrim
HTTP Request
POST /phpuk17/foo HTTP/1.1
Host: www.phpconference.co.uk
foo=bar&baz=bat
@asgrim
HTTP Response
HTTP/1.1 200 OK
Content-Type: text/plain
This is the response body
@asgrim
Layers of an Expressive application
Expressive
Stratigility
Diactoros
PSR-7 Interface
DIRouter Template
Your Appli...
@asgrim
Zend Diactoros
PSR-7 implementation
@asgrim
Node http.Server using Diactoros
$server = ZendDiactorosServer::createServer(
function ($request, $response, $done...
@asgrim
Layers of an Expressive application
Expressive
Stratigility
Diactoros
PSR-7 Interface
DIRouter Template
Your Appli...
@asgrim
Zend Stratigility
Creating & dispatching middleware pipelines
@asgrim
So what is “middleware”?
@asgrim
Middleware in the middle
function(Request $request, DelegateInterface $delegate) : Response
{
// ... some code bef...
@asgrim
http-interop/http-middleware
@asgrim
Modifying the response
function(Request $request, DelegateInterface $delegate) : Response
{
$response = $delegate-...
@asgrim
Pipe all the things!
$pipe = new ZendStratigilityMiddlewarePipe();
$pipe->pipe($logUncaughtErrorsMiddleware);
$pip...
@asgrim
LogErrorsCaughtMiddleware
function(Request $request, DelegateInterface $delegate) : Response
{
try {
return $deleg...
@asgrim
SessionInitialisingMiddleware
function(Request $request, DelegateInterface $delegate) : Response
{
session_start()...
@asgrim
function(Request $request, DelegateInterface $delegate) : Response
{
if (!$this->doSomeOAuthCheck($request)) {
ret...
@asgrim
IndexActionMiddleware
function(Request $request, DelegateInterface $delegate) : Response
{
// ... some code ...
re...
@asgrim
Layers of an Expressive application
Expressive
Stratigility
Diactoros
PSR-7 Interface
DIRouter Template
Your Appli...
@asgrim
Zend Expressive
One Ring to bring them all and in the darkness bind them.
@asgrim
Routing
@asgrim
container-interop
@asgrim
Optionally, templating
@asgrim
Piping and Routing
@asgrim
Zend Framework 2/3
What of them?
@asgrim
Middleware vs MVC
@asgrim
Using ZF components
in Expressive
@asgrim
Module.php
class Module
{
public function getConfig()
{
return include __DIR__ . '/../config/module.config.php';
}...
@asgrim
ConfigProvider
@asgrim
ConfigProvider
namespace ZendForm;
class ConfigProvider
{
public function __invoke()
{
return [
'dependencies' => ...
@asgrim
ConfigProvider#getDependencyConfig()
public function getDependencyConfig()
{
return [
'abstract_factories' => [
Fo...
@asgrim
ZendForm’s Module.php
class Module
{
public function getConfig()
{
$provider = new ConfigProvider();
return [
'ser...
@asgrim
config/autoload/zend-form.global.php
<?php
return (new ZendFormConfigProvider())->__invoke();
@asgrim
Layers of an Expressive application
Expressive
Stratigility
Diactoros
PSR-7 Interface
DIRouter Template
Your Appli...
@asgrim
Getting started
with Zend Expressive
@asgrim
https://github.com/asgrim/book-library
@asgrim
Expressive Skeleton
@asgrim
Expressive installer - start
$ composer create-project zendframework/zend-expressive-skeleton book-library
Install...
@asgrim
Expressive installer - minimal?
Minimal skeleton? (no default middleware, templates, or assets; configuration only...
@asgrim
Expressive installer - router?
Which router do you want to use?
[1] Aura.Router
[2] FastRoute
[3] Zend Router
Make...
@asgrim
Expressive installer - container?
Which container do you want to use for dependency injection?
[1] Aura.Di
[2] Pim...
@asgrim
Expressive installer - template?
Which template engine do you want to use?
[1] Plates
[2] Twig
[3] Zend View insta...
@asgrim
Expressive installer - whoops?
Which error handler do you want to use during development?
[1] Whoops
[n] None of t...
@asgrim
Expressive installer - run it!
$ composer serve
> php -S 0.0.0.0:8080 -t public/ public/index.php
[Thu Sep 1 20:29...
@asgrim
Create the endpoints
@asgrim
Book entity
class Book
{
/**
* @var string
*/
private $id;
/**
* @var bool
*/
private $inStock = true;
public func...
@asgrim
Book entity
class Book
{
/**
* @return void
* @throws AppEntityExceptionBookNotAvailable
*/
public function checkO...
@asgrim
Book entity
class Book
{
/**
* @return void
* @throws AppEntityExceptionBookAlreadyStocked
*/
public function chec...
@asgrim
FindBookByUuidInterface
interface FindBookByUuidInterface
{
/**
* @param UuidInterface $slug
* @return Book
* @thr...
@asgrim
CheckOutAction
public function process(ServerRequestInterface $request, DelegateInterface $delegate): JsonResponse...
@asgrim
Adding some ORM
@asgrim
Your application
Doctrine quick overview
DB
DBAL
ORM
(EntityManager)
Entities
Finders,
Services,
...
@asgrim
DoctrineORMModule
@asgrim
DoctrineORMModule + Expressive?
@asgrim
config/autoload/doctrine-modules.global.php
$vendorPath = __DIR__ . '/../../vendor';
$doctrineModuleConfig = requi...
@asgrim
But wait!
@asgrim
container-interop-doctrine
saves the day!!!
@asgrim
Installation
$ composer require dasprid/container-interop-doctrine
Using version ^0.2.2 for dasprid/container-inte...
@asgrim
config/autoload/doctrine.global.php
<?php
declare(strict_types = 1);
use DoctrineORMEntityManagerInterface;
use Co...
@asgrim
'doctrine' => [
'connection' => [
'orm_default' => [
'driver_class' => PDOPgSqlDriver::class,
'params' => [
'url' ...
@asgrim
'doctrine' => [
'connection' => [
'orm_default' => [
'driver_class' => PDOPgSqlDriver::class,
'params' => [
'url' ...
@asgrim
<?php
declare(strict_types = 1);
use DoctrineORMEntityManagerInterface;
use DoctrineORMToolsConsoleHelperEntityMan...
@asgrim
Annotating the Entities
@asgrim
/**
* @ORMEntity
* @ORMTable(name="book")
*/
class Book
{
/**
* @ORMId
* @ORMColumn(name="id", type="guid")
* @ORM...
@asgrim
/**
* @ORMEntity
* @ORMTable(name="book")
*/
class Book
{
/**
* @ORMId
* @ORMColumn(name="id", type="guid")
* @ORM...
@asgrim
public function __invoke(UuidInterface $id): Book
{
/** @var Book|null $book */
$book = $this->repository->find((s...
@asgrim
try {
$this->entityManager->transactional(function () use ($book) {
$book->checkOut();
});
} catch (BookNotAvailab...
@asgrim
Generate the schema
$ vendor/bin/doctrine orm:schema-tool:create
ATTENTION: This operation should not be executed ...
@asgrim
Insert some data
INSERT INTO book (id, name, in_stock) VALUES (
'1c06bec9-adae-47c2-b411-73b1db850e6f',
'The Great...
@asgrim
/book/1c06bec9-adae-47c2-b411-.../check-out
{"info":"You have checked out The Great Escape"}
@asgrim
/book/1c06bec9-adae-47c2-b411-.../check-in
{"info":"You have checked in The Great Escape"}
@asgrim
Automatic Flushing Middleware
@asgrim
FlushingMiddleware
public function __invoke(Request $request, Response $response, callable $out = null) : Response...
@asgrim
FlushingMiddleware
public function __invoke(Request $request, Response $response, callable $out = null) : Response...
@asgrim
FlushingMiddleware
public function __invoke(Request $request, Response $response, callable $out = null) : Response...
@asgrim
FlushingMiddleware
public function __invoke(Request $request, Response $response, callable $out = null) : Response...
@asgrim
FlushingMiddleware
public function __invoke(Request $request, Response $response, callable $out = null) : Response...
@asgrim
Doing more with
middleware
@asgrim
Authentication
@asgrim
public function __invoke(
Request $request, Response $response, callable $next = null
) : Response {
$queryParams ...
@asgrim
public function __invoke(
Request $request, Response $response, callable $next = null
) : Response {
$queryParams ...
@asgrim
public function __invoke(
Request $request, Response $response, callable $next = null
) : Response {
$queryParams ...
@asgrim
public function __invoke(
Request $request, Response $response, callable $next = null
) : Response {
$queryParams ...
@asgrim
Helios
composer require dasprid/helios
@asgrim
PSR7-Session
composer require psr7-sessions/storageless
@asgrim
public function __invoke(ContainerInterface $container, $_, array $_ = null)
{
$symmetricKey = 'super-secure-key-y...
@asgrim
'routing' => [
'middleware' => [
ApplicationFactory::ROUTING_MIDDLEWARE,
HelperUrlHelperMiddleware::class,
PSR7Ses...
@asgrim
$session = $request->getAttribute(SessionMiddleware::SESSION_ATTRIBUTE);
$session->set('counter', $session->get('c...
@asgrim
To summarise...
● PSR-7 is the foundation for this!
● Diactoros is just a PSR-7 implementation
● Stratigility is a...
Any questions?
https://joind.in/talk/98515
James Titcumb @asgrim
Upcoming SlideShare
Loading in …5
×

of

Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 1 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 2 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 3 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 4 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 5 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 6 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 7 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 8 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 9 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 10 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 11 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 12 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 13 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 14 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 15 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 16 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 17 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 18 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 19 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 20 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 21 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 22 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 23 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 24 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 25 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 26 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 27 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 28 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 29 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 30 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 31 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 32 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 33 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 34 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 35 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 36 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 37 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 38 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 39 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 40 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 41 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 42 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 43 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 44 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 45 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 46 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 47 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 48 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 49 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 50 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 51 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 52 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 53 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 54 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 55 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 56 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 57 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 58 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 59 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 60 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 61 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 62 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 63 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 64 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 65 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 66 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 67 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 68 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 69 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 70 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 71 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 72 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 73 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 74 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 75 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 76 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 77 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 78 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 79 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 80 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 81 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 82 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 83 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 84 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 85 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 86 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 87 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 88 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 89 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 90 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 91 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 92 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 93 Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017) Slide 94
Upcoming SlideShare
Driving Design through Examples
Next
Download to read offline and view in fullscreen.

2 Likes

Share

Download to read offline

Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)

Download to read offline

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.

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all

Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)

  1. 1. @asgrim Kicking off with Zend Expressive and Doctrine ORM James Titcumb PHP UK 2017
  2. 2. Who is this guy? James Titcumb www.jamestitcumb.com www.roave.com www.phphants.co.uk www.phpsouthcoast.co.uk @asgrim
  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 /phpuk17/foo HTTP/1.1 Host: www.phpconference.co.uk 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, DelegateInterface $delegate) : Response { // ... some code before ... $response = $delegate->process($request); // ... some code after ... return $response; }
  16. 16. @asgrim http-interop/http-middleware
  17. 17. @asgrim Modifying the response function(Request $request, DelegateInterface $delegate) : Response { $response = $delegate->process($request); return $response->withHeader( 'X-Clacks-Overhead', 'GNU Terry Pratchett' ); }
  18. 18. @asgrim Pipe all the things! $pipe = new ZendStratigilityMiddlewarePipe(); $pipe->pipe($logUncaughtErrorsMiddleware); $pipe->pipe($sessionInitialisingMiddleware); $pipe->pipe($authenticationMiddleware); $pipe->pipe('/', $indexActionMiddleware); $pipe->pipe(new NotFoundHandler(...));
  19. 19. @asgrim LogErrorsCaughtMiddleware function(Request $request, DelegateInterface $delegate) : Response { try { return $delegate->process($request); } catch (Throwable $throwable) { // Log the error, handle it with error page etc. return new JsonResponse( [ 'message' => $throwable->getMessage(), ], 500 ); } }
  20. 20. @asgrim SessionInitialisingMiddleware function(Request $request, DelegateInterface $delegate) : Response { session_start(); return $delegate->process($request); }
  21. 21. @asgrim function(Request $request, DelegateInterface $delegate) : Response { if (!$this->doSomeOAuthCheck($request)) { return new JsonResponse( [ 'message' => 'Invalid OAuth token', ], 403 ); } return $delegate->process($request); } AuthenticationMiddleware
  22. 22. @asgrim IndexActionMiddleware function(Request $request, DelegateInterface $delegate) : Response { // ... some code ... return new JsonResponse($someData, 200); }
  23. 23. @asgrim Layers of an Expressive application Expressive Stratigility Diactoros PSR-7 Interface DIRouter Template Your Application
  24. 24. @asgrim Zend Expressive One Ring to bring them all and in the darkness bind them.
  25. 25. @asgrim Routing
  26. 26. @asgrim container-interop
  27. 27. @asgrim Optionally, templating
  28. 28. @asgrim Piping and Routing
  29. 29. @asgrim Zend Framework 2/3 What of them?
  30. 30. @asgrim Middleware vs MVC
  31. 31. @asgrim Using ZF components in Expressive
  32. 32. @asgrim Module.php class Module { public function getConfig() { return include __DIR__ . '/../config/module.config.php'; } }
  33. 33. @asgrim ConfigProvider
  34. 34. @asgrim ConfigProvider namespace ZendForm; class ConfigProvider { public function __invoke() { return [ 'dependencies' => $this->getDependencyConfig(), 'view_helpers' => $this->getViewHelperConfig(), ]; } }
  35. 35. @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, ],
  36. 36. @asgrim ZendForm’s Module.php class Module { public function getConfig() { $provider = new ConfigProvider(); return [ 'service_manager' => $provider->getDependencyConfig(), 'view_helpers' => $provider->getViewHelperConfig(), ]; } }
  37. 37. @asgrim config/autoload/zend-form.global.php <?php return (new ZendFormConfigProvider())->__invoke();
  38. 38. @asgrim Layers of an Expressive application Expressive Stratigility Diactoros PSR-7 Interface DIRouter Template Your Application
  39. 39. @asgrim Getting started with Zend Expressive
  40. 40. @asgrim https://github.com/asgrim/book-library
  41. 41. @asgrim Expressive Skeleton
  42. 42. @asgrim Expressive installer - start $ composer create-project zendframework/zend-expressive-skeleton book-library Installing zendframework/zend-expressive-skeleton (1.0.3) - Installing zendframework/zend-expressive-skeleton (1.0.3) Downloading: 100% Created project in book-library > ExpressiveInstallerOptionalPackages::install Setup data and cache dir Setting up optional packages
  43. 43. @asgrim Expressive installer - minimal? Minimal skeleton? (no default middleware, templates, or assets; configuration only) [y] Yes (minimal) [n] No (full; recommended) Make your selection (No): n
  44. 44. @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): 2
  45. 45. @asgrim Expressive installer - container? Which container do you want to use for dependency injection? [1] Aura.Di [2] Pimple [3] Zend ServiceManager Make your selection or type a composer package name and version (Zend ServiceManager): 3
  46. 46. @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): n
  47. 47. @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
  48. 48. @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": "zend-expressive.readthedocs.org" }
  49. 49. @asgrim Create the endpoints
  50. 50. @asgrim Book entity class Book { /** * @var string */ private $id; /** * @var bool */ private $inStock = true; public function __construct() { $this->id = (string)Uuid::uuid4(); }
  51. 51. @asgrim Book entity class Book { /** * @return void * @throws AppEntityExceptionBookNotAvailable */ public function checkOut() { if (!$this->inStock) { throw ExceptionBookNotAvailable::fromBook($this); } $this->inStock = false; }
  52. 52. @asgrim Book entity class Book { /** * @return void * @throws AppEntityExceptionBookAlreadyStocked */ public function checkIn() { if ($this->inStock) { throw ExceptionBookAlreadyStocked::fromBook($this); } $this->inStock = true; }
  53. 53. @asgrim FindBookByUuidInterface interface FindBookByUuidInterface { /** * @param UuidInterface $slug * @return Book * @throws ExceptionBookNotFound */ public function __invoke(UuidInterface $slug): Book; }
  54. 54. @asgrim CheckOutAction public function process(ServerRequestInterface $request, DelegateInterface $delegate): 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()), ]); }
  55. 55. @asgrim Adding some ORM
  56. 56. @asgrim Your application Doctrine quick overview DB DBAL ORM (EntityManager) Entities Finders, Services, ...
  57. 57. @asgrim DoctrineORMModule
  58. 58. @asgrim DoctrineORMModule + Expressive?
  59. 59. @asgrim config/autoload/doctrine-modules.global.php $vendorPath = __DIR__ . '/../../vendor'; $doctrineModuleConfig = require_once $vendorPath . '/doctrine/doctrine-module/config/module.config.php'; $doctrineModuleConfig['dependencies'] = $doctrineModuleConfig['service_manager']; unset($doctrineModuleConfig['service_manager']); $ormModuleConfig = require_once $vendorPath . '/doctrine/doctrine-orm-module/config/module.config.php'; $ormModuleConfig['dependencies'] = $ormModuleConfig['service_manager']; unset($ormModuleConfig['service_manager']); return ArrayUtils::merge($doctrineModuleConfig, $ormModuleConfig);
  60. 60. @asgrim But wait!
  61. 61. @asgrim container-interop-doctrine saves the day!!!
  62. 62. @asgrim Installation $ composer require dasprid/container-interop-doctrine Using version ^0.2.2 for dasprid/container-interop-doctrine ./composer.json has been updated Loading composer repositories with package information Updating dependencies (including require-dev) - Installing dasprid/container-interop-doctrine (0.2.2) Loading from cache Writing lock file Generating autoload files $
  63. 63. @asgrim config/autoload/doctrine.global.php <?php declare(strict_types = 1); use DoctrineORMEntityManagerInterface; use ContainerInteropDoctrineEntityManagerFactory; return [ 'dependencies' => [ 'factories' => [ EntityManagerInterface::class => EntityManagerFactory::class, ], ], ];
  64. 64. @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
  65. 65. @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
  66. 66. @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
  67. 67. @asgrim Annotating the Entities
  68. 68. @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
  69. 69. @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
  70. 70. @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
  71. 71. @asgrim try { $this->entityManager->transactional(function () use ($book) { $book->checkOut(); }); } catch (BookNotAvailable $bookNotAvailable) { return new JsonResponse(['info' => $bookNotAvailable->getMessage()], 423); } src/App/Action/CheckOutAction.php
  72. 72. @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! $
  73. 73. @asgrim Insert some data INSERT INTO book (id, name, in_stock) VALUES ( '1c06bec9-adae-47c2-b411-73b1db850e6f', 'The Great Escape', true );
  74. 74. @asgrim /book/1c06bec9-adae-47c2-b411-.../check-out {"info":"You have checked out The Great Escape"}
  75. 75. @asgrim /book/1c06bec9-adae-47c2-b411-.../check-in {"info":"You have checked in The Great Escape"}
  76. 76. @asgrim Automatic Flushing Middleware
  77. 77. @asgrim FlushingMiddleware public function __invoke(Request $request, Response $response, callable $out = null) : Response { if (null === $out) { throw new InvalidArgumentException('Middleware in ' . __CLASS__ . ' must be piped'); } $response = $out($request, $response); if ($this->entityManager->isOpen()) { $this->entityManager->flush(); } return $response; }
  78. 78. @asgrim FlushingMiddleware public function __invoke(Request $request, Response $response, callable $out = null) : Response { if (null === $out) { throw new InvalidArgumentException('Middleware in ' . __CLASS__ . ' must be piped'); } $response = $out($request, $response); if ($this->entityManager->isOpen()) { $this->entityManager->flush(); } return $response; }
  79. 79. @asgrim FlushingMiddleware public function __invoke(Request $request, Response $response, callable $out = null) : Response { if (null === $out) { throw new InvalidArgumentException('Middleware in ' . __CLASS__ . ' must be piped'); } $response = $out($request, $response); if ($this->entityManager->isOpen()) { $this->entityManager->flush(); } return $response; }
  80. 80. @asgrim FlushingMiddleware public function __invoke(Request $request, Response $response, callable $out = null) : Response { if (null === $out) { throw new InvalidArgumentException('Middleware in ' . __CLASS__ . ' must be piped'); } $response = $out($request, $response); if ($this->entityManager->isOpen()) { $this->entityManager->flush(); } return $response; }
  81. 81. @asgrim FlushingMiddleware public function __invoke(Request $request, Response $response, callable $out = null) : Response { if (null === $out) { throw new InvalidArgumentException('Middleware in ' . __CLASS__ . ' must be piped'); } $response = $out($request, $response); if ($this->entityManager->isOpen()) { $this->entityManager->flush(); } return $response; }
  82. 82. @asgrim Doing more with middleware
  83. 83. @asgrim Authentication
  84. 84. @asgrim public function __invoke( Request $request, Response $response, callable $next = null ) : Response { $queryParams = $request->getQueryParams(); if (!array_key_exists('authenticated', $queryParams)||$queryParams['authenticated'] !== '1') { return new JsonResponse( ['error' => 'You are not authenticated.'], 403 ); } return $next($request, $response); } Create the middleware
  85. 85. @asgrim public function __invoke( Request $request, Response $response, callable $next = null ) : Response { $queryParams = $request->getQueryParams(); if (!array_key_exists('authenticated', $queryParams)||$queryParams['authenticated'] !== '1') { return new JsonResponse( ['error' => 'You are not authenticated.'], 403 ); } return $next($request, $response); } Create the middleware
  86. 86. @asgrim public function __invoke( Request $request, Response $response, callable $next = null ) : Response { $queryParams = $request->getQueryParams(); if (!array_key_exists('authenticated', $queryParams)||$queryParams['authenticated'] !== '1') { return new JsonResponse( ['error' => 'You are not authenticated.'], 403 ); } return $next($request, $response); } Create the middleware
  87. 87. @asgrim public function __invoke( Request $request, Response $response, callable $next = null ) : Response { $queryParams = $request->getQueryParams(); if (!array_key_exists('authenticated', $queryParams)||$queryParams['authenticated'] !== '1') { return new JsonResponse( ['error' => 'You are not authenticated.'], 403 ); } return $next($request, $response); } Create the middleware
  88. 88. @asgrim Helios composer require dasprid/helios
  89. 89. @asgrim PSR7-Session composer require psr7-sessions/storageless
  90. 90. @asgrim public function __invoke(ContainerInterface $container, $_, array $_ = null) { $symmetricKey = 'super-secure-key-you-should-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 SystemCurrentTime() ); } Factory the middleware
  91. 91. @asgrim 'routing' => [ 'middleware' => [ ApplicationFactory::ROUTING_MIDDLEWARE, HelperUrlHelperMiddleware::class, PSR7SessionHttpSessionMiddleware::class, AppMiddlewareAuthenticationMiddleware::class, ApplicationFactory::DISPATCH_MIDDLEWARE, ], 'priority' => 1, ], Add middleware to pipe
  92. 92. @asgrim $session = $request->getAttribute(SessionMiddleware::SESSION_ATTRIBUTE); $session->set('counter', $session->get('counter', 0) + 1); Session is stored in Request
  93. 93. @asgrim To summarise... ● PSR-7 is the foundation for this! ● Diactoros is just a PSR-7 implementation ● Stratigility is a middleware pipeline: the main bit ● Expressive is a glue for everything ● DoctrineModule can be used (with some fiddling) ● container-interop-doctrine makes Doctrine work easier ● Middleware all the things!
  94. 94. Any questions? https://joind.in/talk/98515 James Titcumb @asgrim
  • lukaszadamczewski

    Feb. 15, 2018
  • williammdavis

    Feb. 19, 2017

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.

Views

Total views

3,044

On Slideshare

0

From embeds

0

Number of embeds

2,440

Actions

Downloads

13

Shares

0

Comments

0

Likes

2

×