Top Banner
@asgrim Kicking off with Zend Expressive and Doctrine ORM James Titcumb SunshinePHP 2017
94

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

Feb 09, 2017

Download

Technology

James Titcumb
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Kicking off with Zend Expressiveand Doctrine ORM

James TitcumbSunshinePHP 2017

Page 2: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

Who is this guy?James Titcumbwww.jamestitcumb.com

www.roave.com

www.phphants.co.uk

www.phpsouthcoast.co.uk

@asgrim

Page 3: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

What is Zend Expressive?

Page 4: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Layers of an Expressive application

Expressive

Stratigility

Diactoros

PSR-7 Interface

DIRouter Template

Your Application

Page 5: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Layers of an Expressive application

Expressive

Stratigility

Diactoros

PSR-7 Interface

DIRouter Template

Your Application

Page 6: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

PSR-7HTTP Message Interfaces

Page 7: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

HTTP Request

POST /zendcon2016/foo HTTP/1.1

Host: www.zendcon.com

foo=bar&baz=bat

Page 8: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

HTTP Response

HTTP/1.1 200 OK

Content-Type: text/plain

This is the response body

Page 9: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Layers of an Expressive application

Expressive

Stratigility

Diactoros

PSR-7 Interface

DIRouter Template

Your Application

Page 10: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Zend DiactorosPSR-7 implementation

Page 11: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Node http.Server using Diactoros$server = \Zend\Diactoros\Server::createServer(

function ($request, $response, $done) {

return $response->getBody()->write('hello world');

},

$_SERVER,

$_GET,

$_POST,

$_COOKIE,

$_FILES

);

$server->listen();

Page 12: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Layers of an Expressive application

Expressive

Stratigility

Diactoros

PSR-7 Interface

DIRouter Template

Your Application

Page 13: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Zend StratigilityCreating & dispatching middleware pipelines

Page 14: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

So what is “middleware”?

Page 15: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Middleware in the middlefunction(Request $request, DelegateInterface $delegate) : Response

{

// ... some code before ...

$response = $delegate->process($request);

// ... some code after ...

return $response;

}

Page 16: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

http-interop/http-middleware

Page 17: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Modifying the responsefunction(Request $request, DelegateInterface $delegate) : Response

{

$response = $delegate->process($request);

return $response->withHeader(

'X-Clacks-Overhead',

'GNU Terry Pratchett'

);

}

Page 18: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Pipe all the things!$pipe = new \Zend\Stratigility\MiddlewarePipe();

$pipe->pipe($logUncaughtErrorsMiddleware);

$pipe->pipe($sessionInitialisingMiddleware);

$pipe->pipe($authenticationMiddleware);

$pipe->pipe('/', $indexActionMiddleware);

$pipe->pipe(new NotFoundHandler(...));

Page 19: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

LogErrorsCaughtMiddlewarefunction(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

);

}

}

Page 20: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

SessionInitialisingMiddlewarefunction(Request $request, DelegateInterface $delegate) : Response

{

session_start();

return $delegate->process($request);

}

Page 21: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

function(Request $request, DelegateInterface $delegate) : Response

{

if (!$this->doSomeOAuthCheck($request)) {

return new JsonResponse(

[

'message' => 'Invalid OAuth token',

],

403

);

}

return $delegate->process($request);

}

AuthenticationMiddleware

Page 22: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

IndexActionMiddlewarefunction(Request $request, DelegateInterface $delegate) : Response

{

// ... some code ...

return new JsonResponse($someData, 200);

}

Page 23: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Layers of an Expressive application

Expressive

Stratigility

Diactoros

PSR-7 Interface

DIRouter Template

Your Application

Page 24: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Zend ExpressiveOne Ring to bring them all and in the darkness bind them.

Page 25: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Routing

Page 26: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

container-interop

Page 27: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Optionally, templating

Page 28: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Piping and Routing

Page 29: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Zend Framework 2/3What of them?

Page 30: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Middleware vs MVC

Page 31: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Using ZF componentsin Expressive

Page 32: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Module.phpclass Module

{

public function getConfig()

{

return include __DIR__ . '/../config/module.config.php';

}

}

Page 33: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

ConfigProvider

Page 34: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

ConfigProvidernamespace Zend\Form;

class ConfigProvider

{

public function __invoke()

{

return [

'dependencies' => $this->getDependencyConfig(),

'view_helpers' => $this->getViewHelperConfig(),

];

}

}

Page 35: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

ConfigProvider#getDependencyConfig()public function getDependencyConfig()

{

return [

'abstract_factories' => [

FormAbstractServiceFactory::class,

],

'aliases' => [

'Zend\Form\Annotation\FormAnnotationBuilder' => 'FormAnnotationBuilder',

Annotation\AnnotationBuilder::class => 'FormAnnotationBuilder',

FormElementManager::class => 'FormElementManager',

],

'factories' => [

'FormAnnotationBuilder' => Annotation\AnnotationBuilderFactory::class,

'FormElementManager' => FormElementManagerFactory::class,

],

Page 36: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Zend\Form’s Module.phpclass Module

{

public function getConfig()

{

$provider = new ConfigProvider();

return [

'service_manager' => $provider->getDependencyConfig(),

'view_helpers' => $provider->getViewHelperConfig(),

];

}

}

Page 37: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

config/autoload/zend-form.global.php

<?php

return (new \Zend\Form\ConfigProvider())->__invoke();

Page 38: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Layers of an Expressive application

Expressive

Stratigility

Diactoros

PSR-7 Interface

DIRouter Template

Your Application

Page 39: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Getting startedwith Zend Expressive

Page 40: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

https://github.com/asgrim/book-library

Page 41: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Expressive Skeleton

Page 42: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@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

> ExpressiveInstaller\OptionalPackages::install

Setup data and cache dir

Setting up optional packages

Page 43: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@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

Page 44: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@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

Page 45: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@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

Page 46: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@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

Page 47: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@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

Page 48: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@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"}

Page 49: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Create the endpoints

Page 50: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Book entityclass Book

{

/**

* @var string

*/

private $id;

/**

* @var bool

*/

private $inStock = true;

public function __construct()

{

$this->id = (string)Uuid::uuid4();

}

Page 51: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Book entityclass Book

{

/**

* @return void

* @throws \App\Entity\Exception\BookNotAvailable

*/

public function checkOut()

{

if (!$this->inStock) {

throw Exception\BookNotAvailable::fromBook($this);

}

$this->inStock = false;

}

Page 52: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Book entityclass Book

{

/**

* @return void

* @throws \App\Entity\Exception\BookAlreadyStocked

*/

public function checkIn()

{

if ($this->inStock) {

throw Exception\BookAlreadyStocked::fromBook($this);

}

$this->inStock = true;

}

Page 53: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

FindBookByUuidInterfaceinterface FindBookByUuidInterface

{

/**

* @param UuidInterface $slug

* @return Book

* @throws Exception\BookNotFound

*/

public function __invoke(UuidInterface $slug): Book;

}

Page 54: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

CheckOutActionpublic 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()), ]);}

Page 55: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Adding some ORM

Page 56: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Your application

Doctrine quick overview

DB DBAL ORM(EntityManager) Entities

Finders,Services,

...

Page 57: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

DoctrineORMModule

Page 58: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

DoctrineORMModule + Expressive?

Page 59: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@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);

Page 60: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

But wait!

Page 61: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

container-interop-doctrinesaves the day!!!

Page 62: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@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

$

Page 63: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

config/autoload/doctrine.global.php<?php

declare(strict_types = 1);

use Doctrine\ORM\EntityManagerInterface;

use ContainerInteropDoctrine\EntityManagerFactory;

return [

'dependencies' => [

'factories' => [

EntityManagerInterface::class => EntityManagerFactory::class,

],

],

];

Page 64: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

'doctrine' => [

'connection' => [

'orm_default' => [

'driver_class' => PDOPgSql\Driver::class,

'params' => [

'url' => 'postgres://user:pass@localhost/book_library',

],

],

],

'driver' => [

'orm_default' => [

'class' => MappingDriverChain::class,

'drivers' => [

// ... and so on ...

config/autoload/doctrine.global.php

Page 65: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

'doctrine' => [

'connection' => [

'orm_default' => [

'driver_class' => PDOPgSql\Driver::class,

'params' => [

'url' => 'postgres://user:pass@localhost/book_library',

],

],

],

'driver' => [

'orm_default' => [

'class' => MappingDriverChain::class,

'drivers' => [

// ... and so on ...

config/autoload/doctrine.global.php

Page 66: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

<?php

declare(strict_types = 1);

use Doctrine\ORM\EntityManagerInterface;

use Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper;

use Symfony\Component\Console\Helper\HelperSet;

$container = require __DIR__ . '/container.php';

return new HelperSet([

'em' => new EntityManagerHelper(

$container->get(EntityManagerInterface::class)

),

]);

config/cli-config.php

Page 67: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Annotating the Entities

Page 68: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

/**

* @ORM\Entity

* @ORM\Table(name="book")

*/

class Book

{

/**

* @ORM\Id

* @ORM\Column(name="id", type="guid")

* @ORM\GeneratedValue(strategy="NONE")

* @var string

*/

private $id;

src/App/Entity/Book.php

Page 69: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

/**

* @ORM\Entity

* @ORM\Table(name="book")

*/

class Book

{

/**

* @ORM\Id

* @ORM\Column(name="id", type="guid")

* @ORM\GeneratedValue(strategy="NONE")

* @var string

*/

private $id;

src/App/Entity/Book.php

Page 70: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

public function __invoke(UuidInterface $id): Book

{

/** @var Book|null $book */

$book = $this->repository->find((string)$id);

if (null === $book) {

throw Exception\BookNotFound::fromUuid($id);

}

return $book;

}

src/App/Service/Book/DoctrineFindBookByUuid.php

Page 71: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@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

Page 72: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@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!

$

Page 73: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Insert some dataINSERT INTO book (id, name, in_stock) VALUES (

'1c06bec9-adae-47c2-b411-73b1db850e6f',

'The Great Escape',

true

);

Page 74: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

/book/1c06bec9-adae-47c2-b411-.../check-out

{"info":"You have checked out The Great Escape"}

Page 75: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

/book/1c06bec9-adae-47c2-b411-.../check-in

{"info":"You have checked in The Great Escape"}

Page 76: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Automatic Flushing Middleware

Page 77: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

FlushingMiddlewarepublic 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;

}

Page 78: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

FlushingMiddlewarepublic 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;

}

Page 79: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

FlushingMiddlewarepublic 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;

}

Page 80: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

FlushingMiddlewarepublic 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;

}

Page 81: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

FlushingMiddlewarepublic 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;

}

Page 82: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Doing more with middleware

Page 83: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Authentication

Page 84: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@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

Page 85: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@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

Page 86: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@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

Page 87: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@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

Page 88: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

Helioscomposer require dasprid/helios

Page 89: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

PSR7-Sessioncomposer require psr7-sessions/storageless

Page 90: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@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 Signer\Hmac\Sha256(),

$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

Page 91: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

'routing' => [

'middleware' => [

ApplicationFactory::ROUTING_MIDDLEWARE,

Helper\UrlHelperMiddleware::class,

PSR7Session\Http\SessionMiddleware::class,

App\Middleware\AuthenticationMiddleware::class,

ApplicationFactory::DISPATCH_MIDDLEWARE,

],

'priority' => 1,

],

Add middleware to pipe

Page 92: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@asgrim

$session = $request->getAttribute(SessionMiddleware::SESSION_ATTRIBUTE);

$session->set('counter', $session->get('counter', 0) + 1);

Session is stored in Request

Page 93: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

@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!

Page 94: Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)

Any questions?

https://joind.in/talk/3bf19

James Titcumb @asgrim