O documento resume o Zend Framework 3, focando nos seguintes pontos:
1) Ênfase em componentes independentes ao invés de um framework monolítico;
2) Foco em HTTP e middleware, utilizando PSR-7 e abordagem de pipeline/condutor;
3) Otimizado para PHP 7, mas compatível com PHP 5.5+.
O que esperar do Zend Framework 3: componentes, HTTP, PHP 7 e mais
1. O que esperar do Zend Framework 3
Flávio Gomes da Silva Lisboa
www.fgsl.eti.br
2. 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.
14. ZF1: o passado
● Componentes eram desenvolvidos dentro do
repositório do framework, e
15. ZF1: o passado
● Componentes eram desenvolvidos dentro do
repositório do framework, e
● Eram instaláveis somente com o framework
inteiro.
16. ZF2: o presente
● Componentes são desenvolvidos dentro do
repositório do framework, e
● Podem ser instalados individualmente
(Composer, GIT).
17. ZF 2.5: o presente
● Não há mais pacotes de instalação.
● O repositório ZF depende dos componentes.
18. Instale só o que vai usar
{
"require": {
"zendframework/zend-authentication": "^2.5",
"zendframework/zend-cache": "^2.5",
"zendframework/zend-captcha": "^2.5",
"etc": "*"
}
}
23. HTTP é o fundamento da Web
● Um cliente envia uma requisição
● Um servidor devolve uma resposta
24. Mensagens HTTP
GET /path HTTP/1.1
Host: example.com
Accept: application/json
HTTP/1.1 200 OK
Content-Type: application/json
{"foo":"bar"}
Requisição
Resposta
25. Frameworks modelam mensagens
Mas cada framework faz isso diferente
$method = $request->getMethod();
$method = $request->getRequestMethod();
$method = $request->method;
29. Middleware
Entre a requisição e a resposta
function (Request $request, Response $response)
{
// do some work
return $response; // same, or a new instance.
}
33. Pilhas ou Condutores
$pipeline->pipe($middleware1); // always evaluate
$pipeline->pipe('/path', $middleware2); // only if path matches
$pipeline->pipe('/different/path', $middleware3);
$response = $pipeline->run();
34. Estilo Cebola
class 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);
36. Consumindo Middleware
ZF permitirá despachar o seguinte middleware:
… e controladores ZF serão middleware.
/**
* @return Response
*/
public function (Request $request, Response $response);
37. 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);
}
}
38. Middleware como alternativa para
tempo de execução
● Desempenho
● Experiência do desenvolvedor
● Reusabilidade entre frameworks
40. PSR-7 e Middleware provêem...
● Caminhos para otimização de desempenho
● Interfaces para web mais simples
● Maior interoperabilidade e potencial reuso
42. 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!
43. 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
44. 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);
54. 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.
55. Hello World
(para index.php no web root)
// In index.php
use ZendExpressiveAppFactory;
use PsrHttpMessageResponseInterface;
use PsrHttpMessageRequestInterface;
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
61. 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).
67. Controlador
●
<?php
●
●
namespace AppAction;
●
●
use PsrHttpMessageServerRequestInterface;
●
use PsrHttpMessageResponseInterface;
●
use ZendExpressiveTemplateTemplateRendererInterface;
●
use ZendStratigilityMiddlewareInterface;
●
●
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
68. Fábrica
<?php
namespace AppAction;
use InteropContainerContainerInterface;
use ZendExpressiveTemplateTemplateRendererInterface;
class IndexFactory
{
public function __invoke(ContainerInterface $container)
{
$templateRenderer = $container->get(TemplateRendererInterface::class);
return new IndexAction($templateRenderer);
}
}
src/Action/IndexFactory.php
73. Caching
<?php
namespace App;
use DoctrineCommonCacheFilesystemCache;
use InteropContainerContainerInterface;
use ZendServiceManagerExceptionServiceNotCreatedException;
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
74. Caching
<?php
namespace AppMiddleware;
use DoctrineCommonCacheCache;
use InteropContainerContainerInterface;
class CacheFactory
{
public function __invoke(ContainerInterface $container)
{
$cache = $container->get(Cache::class);
return new CacheMiddleware($cache);
}
}
src/Middleware/CacheFactory.php
75. Caching
<?php
namespace AppMiddleware;
use DoctrineCommonCacheCache;
use PsrHttpMessageResponseInterface;
use PsrHttpMessageServerRequestInterface;
use ZendStratigilityMiddlewareInterface;
class CacheMiddleware implements MiddlewareInterface
{
private $cache;
public function __construct(Cache $cache)
{
$this->cache = $cache;
}
src/Middleware/CacheMiddleware.php
84. 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
87. Instalando um provedor de fotos
<?php
namespace App;
use AndrewCarterUKAPODAPI;
use GuzzleHttpClient;
use InteropContainerContainerInterface;
use ZendServiceManagerExceptionServiceNotCreatedException;
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
88. Instalando um provedor de fotos
<?php
namespace AppAction;
use AndrewCarterUKAPODAPIInterface;
use InteropContainerContainerInterface;
use ZendServiceManagerExceptionServiceNotCreatedException;
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
89. Instalando um provedor de fotos
<?php
namespace AppAction;
use AndrewCarterUKAPODAPIInterface;
use PsrHttpMessageServerRequestInterface;
use PsrHttpMessageResponseInterface;
use ZendStratigilityMiddlewareInterface;
class PictureListAction implements MiddlewareInterface
{
private $apodApi;
private $resultsPerPage;
public function __construct(APIInterface $apodApi, $resultsPerPage)
{
$this->apodApi = $apodApi;
$this->resultsPerPage = $resultsPerPage;
}
src/Action/PictureListAction.php
90. 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.)
91. 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
92. 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(AndrewCarterUKAPODAPIInterface::class)->updateStore(20, $newPictureHandler, $errorHandler);
bin/update.php (cont.)
93. API Key NASA
● https://api.nasa.gov/index.html#live_example
php bin/update.php
95. 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/>