O que esperar do Zend Framework 3

95
O que esperar do Zend Framework 3 Flávio Gomes da Silva Lisboa www.fgsl.eti.br

Transcript of O que esperar do Zend Framework 3

Page 1: O que esperar do Zend Framework 3

O que esperar do Zend Framework 3

Flávio Gomes da Silva Lisboawww.fgsl.eti.br

Page 2: O que esperar do Zend Framework 3

Quem sou eu?

● Bacharel em Ciência da Computação com pós-graduação em Aplicações Corporativas usando Orientação a Objetos e Tecnologia Java pela Universidade Tecnológica Federal do Paraná. Programador formado pelo Centro Estadual de Educação Tecnológica Paula Souza.

● Chefe do setor de adequação da solução e mobilidade do projeto Expresso 3 na Coordenação Estratégica de Ações Governamentais do Serviço Federal de Processamento de Dados (Serpro).

● Zend PHP Certified Engineer, Zend Framework Certified Engineer e Zend Framework 2 Certified Architect.

Page 3: O que esperar do Zend Framework 3

Autor de

20132012201020092008

http://www.novatec.com.br/autores/flaviogomes/

Page 4: O que esperar do Zend Framework 3

Saindo do forno...

Page 5: O que esperar do Zend Framework 3

E em breve...

Zend Framework Componentes Poderosos para PHP 3ª edição

Criando Aplicações PHP com Zend e ExtJS

Page 6: O que esperar do Zend Framework 3

Autor também de

http://www.perse.com.br

Page 7: O que esperar do Zend Framework 3

Escreve no bloghttp://romocavaleirodoespaco.blogspot.com.br/

Page 8: O que esperar do Zend Framework 3

Sumário

● Componentes● HTTP, PSR-7 e Middleware● PHP 7 e PHP 5.5

Page 9: O que esperar do Zend Framework 3

ZF3

● Ênfase em componentes

Page 10: O que esperar do Zend Framework 3

ZF3

● Ênfase em componentes● Foco em HTTP, via PSR-7 e middleware

Page 11: O que esperar do Zend Framework 3

ZF3

● Ênfase em componentes● Foco em HTTP, via PSR-7 e middleware● Otimizado para PHP 7, mas suporta PHP 5.5+

Page 12: O que esperar do Zend Framework 3

ZF3

● Ênfase em componentes● Foco em HTTP, via PSR-7 e middleware● Otimizado para PHP 7, mas suporta PHP 5.5+● Lançamento previsto para...

Page 13: O que esperar do Zend Framework 3

Componentes

Page 14: O que esperar do Zend Framework 3

ZF1: o passado

● Componentes eram desenvolvidos dentro do repositório do framework, e

Page 15: O que esperar do Zend Framework 3

ZF1: o passado

● Componentes eram desenvolvidos dentro do repositório do framework, e

● Eram instaláveis somente com o framework inteiro.

Page 16: O que esperar do Zend Framework 3

ZF2: o presente

● Componentes são desenvolvidos dentro do repositório do framework, e

● Podem ser instalados individualmente (Composer, GIT).

Page 17: O que esperar do Zend Framework 3

ZF 2.5: o presente

● Não há mais pacotes de instalação.● O repositório ZF depende dos componentes.

Page 18: O que esperar do Zend Framework 3

Instale só o que vai usar

{

"require": {

"zendframework/zend-authentication": "^2.5",

"zendframework/zend-cache": "^2.5",

"zendframework/zend-captcha": "^2.5",

"etc": "*"

}

}

Page 19: O que esperar do Zend Framework 3

Por que?

Page 20: O que esperar do Zend Framework 3

Fácil manutenção

● Permite mais times com direitos de alterar código de componentes

● Permite um destino determinístico de repositórios

Page 21: O que esperar do Zend Framework 3

Esqueletos específicos para casos de uso

● Entrega somente serviços?● Precisa de desempenho?● Precisa de tudo?

Haverá um esqueleto para isso!

Page 22: O que esperar do Zend Framework 3

HTTP, PSR-7 e Middleware

Page 23: O que esperar do Zend Framework 3

HTTP é o fundamento da Web

● Um cliente envia uma requisição● Um servidor devolve uma resposta

Page 24: O que esperar do Zend Framework 3

Mensagens HTTP

GET /path HTTP/1.1Host: example.comAccept: application/json

HTTP/1.1 200 OKContent-Type: application/json{"foo":"bar"}

Requisição

Resposta

Page 25: O que esperar do Zend Framework 3

Frameworks modelam mensagens

Mas cada framework faz isso diferente

$method = $request->getMethod();$method = $request->getRequestMethod();$method = $request->method;

Page 26: O que esperar do Zend Framework 3
Page 27: O que esperar do Zend Framework 3

Requisição

$method = $request->getMethod();$accept = $request->getHeader('Accept');$path = $request->getUri()->getPath();$controller = $request->getAttribute('controller');

Page 28: O que esperar do Zend Framework 3

Resposta

$response->getBody()->write('Hello world!');$response = $response ->withStatus(200, 'OK') ->withHeader('Content-Type', 'text/plain');

Page 29: O que esperar do Zend Framework 3

Middleware

Entre a requisição e a resposta

function (Request $request, Response $response){ // do some work return $response; // same, or a new instance.}

Page 30: O que esperar do Zend Framework 3

Uma arquitetura de terceirização

Page 31: O que esperar do Zend Framework 3

Isso parece...

Page 32: O que esperar do Zend Framework 3

Tipos de Middleware

Page 33: O que esperar do Zend Framework 3

Pilhas ou Condutores

$pipeline->pipe($middleware1); // always evaluate$pipeline->pipe('/path', $middleware2); // only if path matches$pipeline->pipe('/different/path', $middleware3);$response = $pipeline->run();

Page 34: O que esperar do Zend Framework 3

Estilo Cebolaclass Outer{ public $inner; public function __invoke($request, $response) { // do some work $response = ($this->inner)($request, $response); // do some work return $response; }}$response = $outer($request, $response);

Page 35: O que esperar do Zend Framework 3

Estilo Lambda

function (Request $request){ // do some work return $response;}$response = $middleware($request);

Page 36: O que esperar do Zend Framework 3

Consumindo Middleware

ZF permitirá despachar o seguinte middleware:

… e controladores ZF serão middleware.

/** * @return Response */public function (Request $request, Response $response);

Page 37: O que esperar do Zend Framework 3

Encapsulador de Middleware para ZF

$middleware = new MvcMiddlewareWrapper( require 'config/application/config.php');class MvcMiddlewareWrapper{ public function __invoke($request, $response) { $app = Application::init($this->config); return $app->dispatch($request, $response); }}

Page 38: O que esperar do Zend Framework 3

Middleware como alternativa para tempo de execução

● Desempenho● Experiência do desenvolvedor● Reusabilidade entre frameworks

Page 39: O que esperar do Zend Framework 3

Exemplo$app = new Middleware();$app->pipe('/', $homepage); // Static!$app->pipe('/customer', $zf2Middleware); // ZF2!$app->pipe('/products', $zf1Middleware); // ZF1!$app->pipe('/api', $apigility); // Apigility!$app->pipe('/user', $userMiddleware); // 3rd party!$server->listen($app);

Page 40: O que esperar do Zend Framework 3

PSR-7 e Middleware provêem...

● Caminhos para otimização de desempenho● Interfaces para web mais simples● Maior interoperabilidade e potencial reuso

Page 41: O que esperar do Zend Framework 3

PHP 7 e PHP 5.5

Page 42: O que esperar do Zend Framework 3

Atualização para o PHP 5.5

● Conseguimos usar traits!● Conseguimos usar a sintaxe curta de array!● Conseguimos usar callable type hint!● Conseguimos usar finally!● Podemos usar a constante mágica ::class!● Conseguimos usar generators!● Conseguimos um PHP mais rápido, mais seguro!

Page 43: O que esperar do Zend Framework 3

PHP 7

Impressionante melhoria de desempenho!

Novo gerenciamento de estruturas de dados no motor do PHP

Novas funcionalidades como declarações de tipo para argumento e retorno

Page 44: O que esperar do Zend Framework 3

PHP 7 : Benchmark

PHP 5.6 PHP 7

Uso de memória 428 MB 33 MB

Tempo de execução 0.49 sec 0.06 sec

$a = array();for ($i = 0; $i < 1000000; $i++) { $a[$i] = array("hello");}echo memory_get_usage(true);

Page 45: O que esperar do Zend Framework 3

Bench.php

Page 46: O que esperar do Zend Framework 3

Wordpress

Page 47: O que esperar do Zend Framework 3

Frameworks

Page 48: O que esperar do Zend Framework 3

ZF3: Otimizado para PHP 7

Atualizar PHP provê melhor segurança, melhora o desempenho e permite melhorar o framework

Page 49: O que esperar do Zend Framework 3

Certo, mas e onde está esse ZF3?

Page 50: O que esperar do Zend Framework 3
Page 51: O que esperar do Zend Framework 3

Não existe Zend Framework 3

Page 52: O que esperar do Zend Framework 3

Mas não tema!

Page 53: O que esperar do Zend Framework 3
Page 54: O que esperar do Zend Framework 3

Zend Expressive

Expressive permite que você escreva aplicações middleware PSR-7 para a web. É um simples micro-framework construído no topo do Stratigility, fornecendo:

● Roteamento dinâmico;● Injeção de dependência via interoperabilidade de

containers;● Templating;● Manipulação de erros.

Page 55: O que esperar do Zend Framework 3

Hello World(para index.php no web root)

// In index.php

use Zend\Expressive\AppFactory;

use Psr\Http\Message\ResponseInterface;

use Psr\Http\Message\RequestInterface;

require 'vendor/autoload.php';

$app = AppFactory::create();

$app->route('/', function (RequestInterface $request,

ResponseInterface $response, $next) {

$response->getBody()->write('Hello, world!');

return $response;

});

$app->run();

php -S 0.0.0.0:8080 -t

Page 56: O que esperar do Zend Framework 3

Instalação com Composer via composer.json

{

"require": {

"zendframework/zend-expressive" : "*",

"zendframework/zend-servicemanager" : "*",

"zendframework/zend-expressive-fastroute" : "*"

}

}

Page 57: O que esperar do Zend Framework 3

Se a rota não casar...

Cannot GET http://[URL DO PROJETO]]

Page 58: O que esperar do Zend Framework 3

Instalação com Composer via terminal

composer require zendframework/zend-expressive aura/router zendframework/zend-servicemanager

Page 59: O que esperar do Zend Framework 3

Anatomia

Page 60: O que esperar do Zend Framework 3

Comparação com ZF2

Page 61: O que esperar do Zend Framework 3

Próximas funcionalidades

Um esqueleto de aplicação;

Criptografia de sessão;

Suporte a cache de HTTP;

Autenticação de usuário (via OAuth2 e/ou outros mecanismos de autenticação).

Page 62: O que esperar do Zend Framework 3

Criando uma galeria de fotos com Zend\Expressive

Page 63: O que esperar do Zend Framework 3

Criando um novo projeto

composer create-project -s rc zendframework/zend-expressive-skeleton <project-directory>

Page 64: O que esperar do Zend Framework 3

Removendo o código desnecessário

rm public/favicon.ico

rm public/zf-logo.png

rm src/Action/*

rm test/Action/*

rm templates/app/*

rm templates/layout/*

Page 65: O que esperar do Zend Framework 3

Configuração do Container

<?php

return [

'dependencies' => [

'factories' => [

Zend\Expressive\Application::class => Zend\Expressive\Container\ApplicationFactory::class,

],

],

];

config/autoload/dependencies.global.php

Page 66: O que esperar do Zend Framework 3

Configuração das Rotas

<?php

return [

'dependencies' => [

'invokables' => [

Zend\Expressive\Router\RouterInterface::class => Zend\Expressive\Router\FastRouteRouter::class,

],

'factories' => [

App\Action\IndexAction::class => App\Action\IndexFactory::class,

]

],

'routes' => [

[

'name' => 'index',

'path' => '/',

'middleware' => App\Action\IndexAction::class,

'allowed_methods' => ['GET'],

],

],

];

config/autoload/routes.global.php

Page 67: O que esperar do Zend Framework 3

Controlador

● <?php●

● namespace App\Action;●

● use Psr\Http\Message\ServerRequestInterface;● use Psr\Http\Message\ResponseInterface;● use Zend\Expressive\Template\TemplateRendererInterface;● use Zend\Stratigility\MiddlewareInterface;●

● class IndexAction implements MiddlewareInterface● {● private $templateRenderer;●

● public function __construct(TemplateRendererInterface $templateRenderer)● {● $this->templateRenderer = $templateRenderer;● }●

● public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)● {● $html = $this->templateRenderer->render('app::index');● $response->getBody()->write($html);● return $response->withHeader('Content-Type', 'text/html');● }● }●

src/Action/IndexAction.php

Page 68: O que esperar do Zend Framework 3

Fábrica

<?php

namespace App\Action;

use Interop\Container\ContainerInterface;

use Zend\Expressive\Template\TemplateRendererInterface;

class IndexFactory

{

public function __invoke(ContainerInterface $container)

{

$templateRenderer = $container->get(TemplateRendererInterface::class);

return new IndexAction($templateRenderer);

}

}

src/Action/IndexFactory.php

Page 69: O que esperar do Zend Framework 3

Templating

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8" />

<title><?=$this->e($title);?></title>

</head>

<body>

<?=$this->section('content')?>

</body>

</html>

templates/layout/default.phtml

Page 70: O que esperar do Zend Framework 3

Caching

composer require doctrine/cache ^1.5

mkdir data/doctrine-cache

Page 71: O que esperar do Zend Framework 3

Caching

<?php

return [

'dependencies' => [

'factories' => [

// ...

Doctrine\Common\Cache\Cache::class => App\DoctrineCacheFactory::class,

],

],

'application' => [

'cache_path' => 'data/doctrine-cache/',

],

];

config/autoload/dependencies.global.php

Page 72: O que esperar do Zend Framework 3

Caching

<?php

return [

'dependencies' => [

'factories' => [

App\Middleware\CacheMiddleware::class => App\Middleware\CacheFactory::class,

]

],

'middleware_pipeline' => [

'pre_routing' => [

[ 'middleware' => App\Middleware\CacheMiddleware::class ],

],

'post_routing' => [

],

],

];

config/autoload/middleware-pipeline.global.php

Page 73: O que esperar do Zend Framework 3

Caching

<?php

namespace App;

use Doctrine\Common\Cache\FilesystemCache;

use Interop\Container\ContainerInterface;

use Zend\ServiceManager\Exception\ServiceNotCreatedException;

class DoctrineCacheFactory

{

public function __invoke(ContainerInterface $container)

{

$config = $container->get('config');

if (!isset($config['application']['cache_path'])) {

throw new ServiceNotCreatedException('cache_path must be set in application configuration');

}

return new FilesystemCache($config['application']['cache_path']);

}

}

src/DoctrineCacheFactory.php

Page 74: O que esperar do Zend Framework 3

Caching

<?php

namespace App\Middleware;

use Doctrine\Common\Cache\Cache;

use Interop\Container\ContainerInterface;

class CacheFactory

{

public function __invoke(ContainerInterface $container)

{

$cache = $container->get(Cache::class);

return new CacheMiddleware($cache);

}

}

src/Middleware/CacheFactory.php

Page 75: O que esperar do Zend Framework 3

Caching

<?php

namespace App\Middleware;

use Doctrine\Common\Cache\Cache;

use Psr\Http\Message\ResponseInterface;

use Psr\Http\Message\ServerRequestInterface;

use Zend\Stratigility\MiddlewareInterface;

class CacheMiddleware implements MiddlewareInterface

{

private $cache;

public function __construct(Cache $cache)

{

$this->cache = $cache;

}

src/Middleware/CacheMiddleware.php

Page 76: O que esperar do Zend Framework 3

Caching

public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)

{

$cachedResponse = $this->getCachedResponse($request, $response);

if (null !== $cachedResponse) {

return $cachedResponse;

}

$response = $next($request, $response);

$this->cacheResponse($request, $response);

return $response;

}

src/Middleware/CacheMiddleware.php (cont.)

Page 77: O que esperar do Zend Framework 3

Caching

private function getCacheKey(ServerRequestInterface $request)

{

return 'http-cache:'.$request->getUri()->getPath();

}

src/Middleware/CacheMiddleware.php (cont.)

Page 78: O que esperar do Zend Framework 3

Caching

private function getCachedResponse(ServerRequestInterface $request, ResponseInterface $response)

{

if ('GET' !== $request->getMethod()) {

return null;

}

$item = $this->cache->fetch($this->getCacheKey($request));

if (false === $item) {

return null;

}

$response->getBody()->write($item['body']);

foreach ($item['headers'] as $name => $value) {

$response = $response->withHeader($name, $value);

}

return $response;

}

src/Middleware/CacheMiddleware.php (cont.)

Page 79: O que esperar do Zend Framework 3

Caching

private function cacheResponse(ServerRequestInterface $request, ResponseInterface $response)

{

if ('GET' !== $request->getMethod() || !$response->hasHeader('Cache-Control')) {

return;

}

$cacheControl = $response->getHeader('Cache-Control');

$abortTokens = array('private', 'no-cache', 'no-store');

if (count(array_intersect($abortTokens, $cacheControl)) > 0) {

return;

}

src/Middleware/CacheMiddleware.php (cont.)

Page 80: O que esperar do Zend Framework 3

Caching

foreach ($cacheControl as $value) {

$parts = explode('=', $value);

if (count($parts) == 2 && 'max-age' === $parts[0]) {

$this->cache->save($this->getCacheKey($request), [

'body' => (string) $response->getBody(),

'headers' => $response->getHeaders(),

], intval($parts[1]));

return;

}

}

}

}

src/Middleware/CacheMiddleware.php (cont.)

Page 81: O que esperar do Zend Framework 3

Caching

rm -rf data/doctrine-cache/*

Limpeza de cache

Page 82: O que esperar do Zend Framework 3

Instalando um provedor de fotos

composer require andrewcarteruk/astronomy-picture-of-the-day ^0.1

NASA Astronomy Picture of the Day - API Wrapper

Page 83: O que esperar do Zend Framework 3

Instalando um provedor de fotos

<?php

return [

'dependencies' => [

'factories' => [

// ...

AndrewCarterUK\APOD\APIInterface::class => App\APIFactory::class,

],

],

'application' => [

// ...

'results_per_page' => 24,

'apod_api' => [

'store_path' => 'public/apod',

'base_url' => '/apod',

],

],

];

config/autoload/dependencies.global.php

Page 84: O que esperar do Zend Framework 3

Instalando um provedor de fotos

<?php

return [

'application' => [

'apod_api' => [

'api_key' => 'DEMO_KEY',

// DEMO_KEY might be good for a couple of requests

// Get your own here: https://api.nasa.gov/index.html#live_example

],

],

];

config/autoload/dependencies.local.php

Page 85: O que esperar do Zend Framework 3

Instalando um provedor de fotos

<?php

return [

'dependencies' => [

// ...

'factories' => [

// ...

App\Action\PictureListAction::class => App\Action\PictureListFactory::class,

],

],

'routes' => [

// ...

[

'name' => 'picture-list',

'path' => '/picture-list[/{page:\d+}]',

'middleware' => App\Action\PictureListAction::class,

'allowed_methods' => ['GET'],

],

],

];

config/autoload/routes.global.php

Page 86: O que esperar do Zend Framework 3

Instalando um provedor de fotos

mkdir public/apod

Diretório de thumbnails

Page 87: O que esperar do Zend Framework 3

Instalando um provedor de fotos

<?php

namespace App;

use AndrewCarterUK\APOD\API;

use GuzzleHttp\Client;

use Interop\Container\ContainerInterface;

use Zend\ServiceManager\Exception\ServiceNotCreatedException;

class APIFactory

{

public function __invoke(ContainerInterface $container)

{

$config = $container->get('config');

if (!isset($config['application']['apod_api'])) {

throw new ServiceNotCreatedException('apod_api must be set in application configuration');

}

return new API(new Client, $config['application']['apod_api']);

}

}

src/APIFactory.php

Page 88: O que esperar do Zend Framework 3

Instalando um provedor de fotos

<?php

namespace App\Action;

use AndrewCarterUK\APOD\APIInterface;

use Interop\Container\ContainerInterface;

use Zend\ServiceManager\Exception\ServiceNotCreatedException;

class PictureListFactory

{

public function __invoke(ContainerInterface $container)

{

$apodApi = $container->get(APIInterface::class);

$config = $container->get('config');

if (!isset($config['application']['results_per_page'])) {

throw new ServiceNotCreatedException('results_per_page must be set in application configuration');

}

return new PictureListAction($apodApi, $config['application']['results_per_page']);

}

}

src/Action/PictureListFactory.php

Page 89: O que esperar do Zend Framework 3

Instalando um provedor de fotos

<?php

namespace App\Action;

use AndrewCarterUK\APOD\APIInterface;

use Psr\Http\Message\ServerRequestInterface;

use Psr\Http\Message\ResponseInterface;

use Zend\Stratigility\MiddlewareInterface;

class PictureListAction implements MiddlewareInterface

{

private $apodApi;

private $resultsPerPage;

public function __construct(APIInterface $apodApi, $resultsPerPage)

{

$this->apodApi = $apodApi;

$this->resultsPerPage = $resultsPerPage;

}

src/Action/PictureListAction.php

Page 90: O que esperar do Zend Framework 3

Instalando um provedor de fotos

public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $out = null)

{

$page = intval($request->getAttribute('page')) ?: 0;

$pictures = $this->apodApi->getPage($page, $this->resultsPerPage);

$response->getBody()->write(json_encode($pictures));

return $response

// ->withHeader('Cache-Control', ['public', 'max-age=3600'])

->withHeader('Content-Type', 'application/json');

}

}

src/Action/PictureListAction.php (cont.)

Page 91: O que esperar do Zend Framework 3

Instalando um provedor de fotos

<?php

chdir(__DIR__.'/..');

include 'vendor/autoload.php';

$container = include 'config/container.php';

// Create a SIGINT handler that sets a shutdown flag

$shutdown = false;

declare(ticks = 1);

pcntl_signal(SIGINT, function () use (&$shutdown) {

$shutdown = true;

});

bin/update.php

Page 92: O que esperar do Zend Framework 3

Instalando um provedor de fotos

$newPictureHandler = function (array $picture) use (&$shutdown) {

echo 'Added: ' . $picture['title'] . PHP_EOL;

// If the shutdown flag has been set, die

if ($shutdown) {

die;

}

};

$errorHandler = function (Exception $exception) use (&$shutdown) {

echo (string) $exception . PHP_EOL;

// If the shutdown flag has been set, die

if ($shutdown) {

die;

}

};

$container->get(AndrewCarterUK\APOD\APIInterface::class)->updateStore(20, $newPictureHandler, $errorHandler);

bin/update.php (cont.)

Page 93: O que esperar do Zend Framework 3

API Key NASA

● https://api.nasa.gov/index.html#live_example

php bin/update.php

Page 94: O que esperar do Zend Framework 3

Onde estará o ZF3?

Page 95: O que esperar do Zend Framework 3

Referência

● Zimuel, E. Pushing Boundaries: Zend Framework 3. Disponível em <http://zimuel.it/slides/phpday2015>

● Ikhsan, A. M. e O'Phinney, M. W. How to Build a NASA Photo Gallery with Zend Expressive. Disponível em <http://www.sitepoint.com/build-nasa-photo-gallery-zend-expressive/>