O que esperar do Zend Framework 2

166
Existe uma coisa que um programador PHP não pode ter... MEDO!

description

Novidades do Zend Framework 2. Palestra proferida na PHP Conference Brasil 2011.

Transcript of O que esperar do Zend Framework 2

Page 1: O que esperar do Zend Framework 2

Existe uma coisa que um programador PHP não pode ter...

MEDO!

Page 2: O que esperar do Zend Framework 2

Advertência

Alguns exemplos de código são exemplos de como implementar construções com Zend Framework 2 e não do Zend Framework 2.

Alguns exemplos fazem uso de construções disponíveis apenas no PHP 5.4.

Page 3: O que esperar do Zend Framework 2

Advertência

Esta apresentação não visa saciar sua sede de conhecimento, mas deixar você sedento por ele.

Page 4: O que esperar do Zend Framework 2

O que esperar do Zend Framework 2

@fgsl

Flávio Gomes da Silva Lisboa

www.fgsl.eti.br

Page 5: O que esperar do Zend Framework 2
Page 6: O que esperar do Zend Framework 2

ESGOTADO

@eminetto

Inspirador Inspirado

@fgsl

Desde 2008 capacitando profissionais em Zend Framework

ESGOTADO

Page 7: O que esperar do Zend Framework 2

Uma Breve História do ZF

Flávio Gomes da Silva Lisboa

Page 8: O que esperar do Zend Framework 2

A Gênese

Outubro de 2005: o projeto é anunciado Março de 2006: primeiro release público,

0.1.0 Final de 2006: Reescrita do MVC

Page 9: O que esperar do Zend Framework 2

1.0.0, julho de 2007

Primeiro release estável Sistema básico de MVC,

com plugins, action helpers, renderização automatizada, etc.

Muitos consumidores de APIs de web services

Classes servidoras para XML-RPC e REST.

Page 10: O que esperar do Zend Framework 2

Primeiro release menor Zend_Form Zend_Layout Sistema de view helper ciente

do layout

1.5.0 – Março de 2008

Layout content

View content

Page 11: O que esperar do Zend Framework 2

1.6.0 – Setembro de 2008

Integração com Dojo Zend_Test: extensão PHPUnit

para controladores Action helper ContextSwitch

HTML

XML

JSON

Page 12: O que esperar do Zend Framework 2

1.7.0 – Novembro de 2008

Suporte à AMF Melhorias de performance

Page 13: O que esperar do Zend Framework 2

1.8.0 – Abril de 2009

Zend_Tool Zend_Application

AMPLAMENTE USADO!

Matthew O'Phinney, ZF Leader e autor do conteúdo no qual esta apresentação se baseia

Page 14: O que esperar do Zend Framework 2

1.9.0 – Agosto de 2009

Zend_Feed_Reader Suporte/compatibilidade

com PHP 5.3 Adições levadas pela

comunidade Início da caça mensal a

bugs

Page 15: O que esperar do Zend Framework 2

1.10.0 – Janeiro de 2009

Integração de ControllerTestCase com Zend_Application

Adição de Zend_Feed_Writer Mudanças na documentação:

adoção do PhD para renderizar o manual do usuário, introdução do sistema de comentário e a seção “Learning Zend Framework”

Page 16: O que esperar do Zend Framework 2

1.11.0 – Novembro de 2010

Suporte mobile via Zend_Http_UserAgent

API SimpleCloud via Zend_Cloud

Page 17: O que esperar do Zend Framework 2

Arquitetura

Page 18: O que esperar do Zend Framework 2

Arquitetura

Page 19: O que esperar do Zend Framework 2

Arquitetura

Page 20: O que esperar do Zend Framework 2

Flexibilidade

Page 21: O que esperar do Zend Framework 2

Liberdade de Escolha

Page 22: O que esperar do Zend Framework 2

E daqui vamos para onde?

Page 23: O que esperar do Zend Framework 2

Revolução

Page 24: O que esperar do Zend Framework 2

Inevitável

Page 25: O que esperar do Zend Framework 2

Junte-se ou morra!

Page 26: O que esperar do Zend Framework 2

Evolução

“A mutação é a chave para a nossa evolução. Ela nos permitiu evoluir de um organismo unicelular à espécie dominante do planeta. O processo é lento, normalmente leva milhares e milhares de anos. Mas em algumas centenas de milênios a evolução dá um salto.”

Page 27: O que esperar do Zend Framework 2

Evolução

Page 28: O que esperar do Zend Framework 2

O foco do Zend Framework 2.0 é na melhoria da consistência e performance.

Page 29: O que esperar do Zend Framework 2

Código Explícito

Não é isto:

class SoraniknatuControllerextends Zend_Controller_Action{public function useTheRingAction(){$this->view->object = 'imagination';}}

Onde isso está

definido?

Quando ocorre a

renderização?

E os layouts?

Page 30: O que esperar do Zend Framework 2

Mágica ou

Bruxaria?

Page 31: O que esperar do Zend Framework 2

Código Explícito

Código explícito é fácil de entender. Código explícito é fácil de analisar. Código explícito é fácil de manter.

Page 32: O que esperar do Zend Framework 2

Melhorias incrementais

Page 33: O que esperar do Zend Framework 2

Conversão de código dos prefixos de fornecedor (por exemplo “Zend_Phaser”) para namespaces do PHP 5.3

Refatoração das exceções Somente autoload Melhoria e padronização do sistema de plugins

Passos de Bebê

Page 34: O que esperar do Zend Framework 2

Reescrever somente onde faz sentido

Page 35: O que esperar do Zend Framework 2

Mudanças na Infraestrutura

Page 36: O que esperar do Zend Framework 2

Namespaces

Page 37: O que esperar do Zend Framework 2

O problema

Nomes de classes muito grandes Dificuldade de refatorar Dificuldade de reter semântica com nomes mais

curtos

Zend_Form_Decorator_Marker_File_Interface

Page 38: O que esperar do Zend Framework 2

A solução

Cada arquivo de classe declara uma namespace

Um namespace por arquivo Qualquer classe usada que não estiver no

namespace atual (ou em um subnamespace) é importada e tipicamente apelidada

A resolução global é desencorajada, exceto no caso de classes referenciadas em strings.

Page 39: O que esperar do Zend Framework 2

Exemplo de Namespace

namespace Zend\EventManager;

use Zend\Stdlib\CallbackHandler;

class EventManager implements EventCollection{/* ... */}

Page 40: O que esperar do Zend Framework 2

Usando Apelidos

namespace Zend\Mvc;

use Zend\Stdlib\Dispatchable,Zend\Di\ServiceLocator as Locator;

class FrontController implements Dispatchable{public function __construct(Locator $locator){$this->serviceLocator = $locator;}}

Page 41: O que esperar do Zend Framework 2

Recomendação para Migração

Importe classes com o comando use em vez de fazer chamadas com require_once em seu código!

Page 42: O que esperar do Zend Framework 2

Importando Classes

use Zend_Controller_Action as Controller;

class PowerController extends Controller{

}

use Zend\Controller\Action as Controller;

class PowerController extends Controller{

}

ZF1

ZF2

Como ficará:

Page 43: O que esperar do Zend Framework 2

Nomeação

Todo código no projeto está no namespace “Zend”

Cada componente define um namespace único Classes dentro de um componente residem

naquele namespace ou em um subnamespace Tipicamente, uma classe nomeada de acordo

com o componente é a classe gateway.

Page 44: O que esperar do Zend Framework 2

Exemplos de Nomeação

namespace Zend\EventManager;

class EventManager implements EventCollection{

}

Page 45: O que esperar do Zend Framework 2

Interfaces

Page 46: O que esperar do Zend Framework 2

Interfaces

Interfaces são nomeadas de acordo com nomes e adjetivos, e descrevem o que elas provêem

Na maioria dos casos, implementações concretas interfaces residem em um subnamespace nomeado de acordo com a interface

Um paradigma Orientado a Contrato mais forte

Page 47: O que esperar do Zend Framework 2

Exemplo de Interfaces

namespace Zend\Session;

use Traversable, ArrayAccess, Serializable, Countable;

interface Storage extends Traversable, ArrayAccess, Serializable, Countable{

}

Page 48: O que esperar do Zend Framework 2

Implementação Concreta

namespace Zend\Session\Storage;

use ArrayObject,Zend\Session\Storage,Zend\Session\Exception;

class ArrayStorage extends ArrayObject implements Storage{/* ... */}

Page 49: O que esperar do Zend Framework 2

Exceções

Page 50: O que esperar do Zend Framework 2

O problema

Todas as exceções derivavam de uma classe comum

Incapacidade de estender os tipos de exceção semânticas oferecidas na SPL

Estratégias de captura limitadas Forte dependência para cada e todos os

componenentes

Page 51: O que esperar do Zend Framework 2

Abordagem ZF2

Zend_Exception foi eliminado Cada componente define uma interface

Exception marcadora Exceções concretas residem em um

subnamespace Exception, e estendem exceções SPL

Page 52: O que esperar do Zend Framework 2

O que a solução provê

Captura tipos de exceções específicas Captura tipos de exceções SPL Captura exceções no nível do componente Captura baseada no tipo de exceção global

Page 53: O que esperar do Zend Framework 2

Definições de Exceçãonamespace Zend\EventManager;

interface Exception{

}

namespace Zend\EventManager\Exception;

use Zend\EventManager\Exception;

class InvalidArgumentException extends \InvalidArgumentException implements Exception{

}

Page 54: O que esperar do Zend Framework 2

Capturando Exceções

namespace Zend\EventManager\Exception;

use Zend\EventManager\Exception;

try {$events->trigger('dom.quixote', $object);} catch (InvalidArgumentException $e) {} catch (Exception $e) {} catch (\InvalidArgumentException $e) {} catch (\Exception $e) {}

Page 55: O que esperar do Zend Framework 2

Autocarregamento

Page 56: O que esperar do Zend Framework 2

O problema

Problemas de performance Muitas classes são usadas apenas no momento

adequado e não devem ser carregadas até que seja necessário.

A falta de chamadas require_once leva a erros.

Page 57: O que esperar do Zend Framework 2

Abordagem ZF2

Chega de chamadas require_once! Múltiplas abordagens de autocarregamento

Autocarregador via include_path estilo ZF1 Autocarregamento pelo namespace / prefixo do

fornecedor Autocarregamento por Mapa de Classes

Page 58: O que esperar do Zend Framework 2

Autocarregamento estilo ZF1

require_once 'Zend/Loader/StandardAutoloader.php';$loader = new Zend\Loader\StandardAutoloader(array('fallback_autoloader' => true,));$loader->register();

EXEMPLO

Page 59: O que esperar do Zend Framework 2

Autocarregamento Namespace/Prefixo ZF2

require_once 'Zend/Loader/StandardAutoloader.php';$loader = new Zend\Loader\StandardAutoloader();$loader->registerNamespace('My', __DIR__ . '/../library/My')->registerPrefix('Fgsl_', __DIR__ . '/../library/Fgsl');$loader->register();

EXEMPLO

Page 60: O que esperar do Zend Framework 2

Autocarregamento com Mapas de Classes

return array('Green\Lantern\Hal' => __DIR__ . '/Lantern/Hal.php',);

require_once 'Zend/Loader/ClassMapAutoloader.php';$loader = new Zend\Loader\ClassMapAutoloader();$loader->registerAutoloadMap(__DIR__ . '/../library/.classmap.php');$loader->register();

Page 61: O que esperar do Zend Framework 2

Mapas de Classes? Mas não dá trabalho pra fazer?

Sim, dá trabalho. Mas nós temos uma ferramenta, bin/classmap_generator.php

E o uso é trivial:

A execução desse script cria o Mapa de Classes em .classmap.php

prompt> cd your/libraryprompt> php /path/to/classmap_generator.php -w

Page 62: O que esperar do Zend Framework 2

Por que?

Mapas de Classes mostram 25% de melhoria no carregador do ZF1 quando não é usada aceleração.

E 60-85% quando um cache de opcode está em uso.

O emparelhamento namespaces/prefixos com caminhos especificados mostra um ganho de 10% sem aceleração.

E 40% de melhoria quando uma cache de opcode é usado.

Page 63: O que esperar do Zend Framework 2

Fábrica de Autocarregadores

Com múltiplas estratégias vem a necessidade por uma fábrica.

Escolha diversas estratégias: Mapa de Classes para pesquisa mais rápida Caminhos namespace/prefixo para código comum Autocarregador de reserva estilo ZF1/PSR-0 para

desenvolvimento

PSR: PHP Specification Request

Page 64: O que esperar do Zend Framework 2

Exemplo de Fábrica de Autocarregadores

require_once 'Zend/Loader/AutoloaderFactory.php';use Zend\Loader\AutoloaderFactory;AutoloaderFactory::factory(array('Zend\Loader\ClassMapAutoloader' => array(__DIR__ . '/../library/.classmap.php',__DIR__ . '/../application/.classmap.php',),'Zend\Loader\StandardAutoloader' => array('namespaces' => array('Zend' => __DIR__ . '/../library/Zend',),'fallback_autoloader' => true,),));

Page 65: O que esperar do Zend Framework 2

Quando posso migrar?

Você pode usar os autocarregadores e as facilidades de geração dos mapas de classe do ZF2... hoje! Pode começar a migração!

Page 66: O que esperar do Zend Framework 2

Carregamento de Plugins

Page 67: O que esperar do Zend Framework 2

Terminologia

Para nossos propósitos, um “plugin” é qualquer classe que é determinada em tempo de execução.

Auxiliares de Controle e Visão Adaptadores Filtros e Validadores

Page 68: O que esperar do Zend Framework 2

Plugins

Page 69: O que esperar do Zend Framework 2

O Problema

Variar abordagens para descobrir classes plugin

Caminhos relativos para as classes chamadas Pilhas prexifo-caminho (mais comum) Modificadores para indicar classes

A abordagem mais comum é terrível Má performance Difícil de depurar Sem caching de plugins descobertos

Page 70: O que esperar do Zend Framework 2

Abordagem ZF2: o Agente de Plugins

Interface de Localização de Plugins Permite variar a implementação de pesquisa de

plugins

Interface de Agente de Plugins Compõe um Localizador de Plugins

Page 71: O que esperar do Zend Framework 2

Interface de Localização de Plugins

namespace Zend\Loader;interface ShortNameLocator{public function isLoaded($name);public function getClassName($name);public function load($name);}

Page 72: O que esperar do Zend Framework 2

Interface de Agente de Plugins

namespace Zend\Loader;interface Broker{public function load($plugin, array $options = null);public function getPlugins();public function isLoaded($name);public function register($name, $plugin);public function unregister($name);public function setClassLoader(ShortNameLocator $loader);public function getClassLoader();}

Page 73: O que esperar do Zend Framework 2

Como usar?

Crie um carregador de plugins padrão Crie um agente de plugins padrão Componha um agente dentro de sua classe Opcionalmente, defina configuração estática Opcionalmente, passe a configuração de

agente e carregador Opcionalmente, registre plugins com o

localizador ou o agente

Page 74: O que esperar do Zend Framework 2

Implementação do Localizador de Plugins

namespace Zend\View;use Zend\Loader\PluginClassLoader;class HelperLoader extends PluginClassLoader{/** * @var array Pre-aliased view helpers */protected $plugins = array('action'=> 'Zend\View\Helper\Action','base_url' => 'Zend\View\Helper\BaseUrl',/* ... */);}

Page 75: O que esperar do Zend Framework 2

Implementação do Agente de Plugins

class HelperBroker extends PluginBroker{protected $defaultClassLoader = 'Zend\View\HelperLoader';public function load($plugin, array $options = null){$helper = parent::load($plugin, $options);if (null !== ($view = $this->getView())) {$helper->setView($view);}return $helper;}protected function validatePlugin($plugin){if (! $plugin instanceof Helper) {throw new InvalidHelperException();}return true;}}

Page 76: O que esperar do Zend Framework 2

Compondo um Agenteuse Zend\View\HelperLoader;class Sinestro{protected $broker;public function broker($spec = null, array $options = array()){if ($spec instanceof Broker) {$this->broker = $spec;return $spec;} elseif (null === $this->broker) {$this->broker = new PluginBroker();}if (null === $spec) {return $this->broker;} elseif (!is_string($spec)) {throw new \Exception();}return $this->broker->load($spec, $options);}}

Page 77: O que esperar do Zend Framework 2

Precedência dos Localizadores

(Do menos para o mais específico) Mapa definido no carregador de plugins

concreto Mapas estáticos ( o registro mais recente tem

precedência) Mapeamento passado via instanciação Mapeamento explícito provido

programaticamente

Page 78: O que esperar do Zend Framework 2

Definindo Mapas Estáticos

use Zend\View\HelperLoader;HelperLoader::addStaticMap(array('url'=> 'Kilowog\Helper\Url','base_url' => 'Project\Helper\BaseUrl',));$loader = new HelperLoader();$class = $loader->load('url'); // "Kilowog\Helper\Url"

Page 79: O que esperar do Zend Framework 2

Passando Mapas via Configuração

use Zend\View\HelperLoader;$config = array('url'=> 'Kilowog\Helper\Url','base_url' => 'Project\Helper\BaseUrl',);$loader = new HelperLoader($config);$class = $loader->load('url'); // "Kilowog\Helper\Url"

Page 80: O que esperar do Zend Framework 2

Passando Mapas para Mapas!

use Zend\View\HelperLoader,Zend\Loader\PluginClassLoader;class HelperMap extends PluginClassLoader{protected $plugins = array('url'=> 'Kilowog\Helper\Url','base_url' => 'Project\Helper\BaseUrl',);}$helpers = new HelperMap();$loader = new HelperLoader($helpers);$class= $loader->load('url'); // "Kilowog\Helper\Url"

Page 81: O que esperar do Zend Framework 2

Estendendo Carregadoresuse Zend\View\HelperLoader;class HelperMap extends HelperLoader{public function __construct($options = null){// Adiciona e/ou sobrescreve o mapa do HelperLoader$this->registerPlugins(array('url'=> 'Kilowog\Helper\Url','base_url' => 'Project\Helper\BaseUrl',));parent::__construct($options);}}$helpers = new HelperMap();$class= $loader->load('url'); // "Kilowog\Helper\Url"

Page 82: O que esperar do Zend Framework 2

Passando Mapas via Agente

use Zend\View\HelperBroker;$broker = new HelperBroker(array('class_loader' => array('class'=> 'HelperMap','options' => array('base_url' => 'App\Helper\BaseUrl',),),));$plugin = $broker->load('base_url'); // "App\Helper\BaseUrl"

Page 83: O que esperar do Zend Framework 2

Criando Mapas Manualmente

use Zend\View\HelperLoader;$loader = new HelperLoader();$loader->registerPlugin('url', 'Kilowog\Helper\Url')->registerPlugins(array('base_url' => 'Project\Helper\BaseUrl',));$class = $loader->load('url'); // "Kilowog\Helper\Url"

Page 84: O que esperar do Zend Framework 2

Gerenciando Plugins via Agente

Por padrão, o carregador é consultado para um nome de classe, e instancia a classe com os argumentos dados

Opcionalmente, você pode alimentar o agente, registrando objetos plugins manualmente sob um dado nome

Page 85: O que esperar do Zend Framework 2

Registrando um Plugin com o Agente

use Kilowog\Helper\Url;// Assume:// - $request == objeto Request// - $router == objeto Router// - $broker == HelperBroker

$url = new Url($request, $router);$broker->registerPlugin('url', $url); // OU:$broker->registerPlugins(array('url' => $url,));$url = $broker->load('url'); // === $url acima

Page 86: O que esperar do Zend Framework 2

E sobre o carregamento tardio?

Frequentemente você precisa configurar plugins

Mas você quer uma instância só quando ela for realmente requisitada

É aí que entra Zend\Loader\LazyLoadingBroker

Page 87: O que esperar do Zend Framework 2

LazyLoadingBroker Interface

namespace Zend\Loader;interface LazyLoadingBroker extends Broker{public function registerSpec($name, array $spec = null);public function registerSpecs($specs);public function unregisterSpec($name);public function getRegisteredPlugins();public function hasPlugin($name);}

Page 88: O que esperar do Zend Framework 2

Usando LazyLoadingBroker

Registra “especificações” com o agente Quando o plugin é requisitado, as opções

fornecidas serão usadas a menos que novas opções sejam passadas

De todas as outras maneiras, ele comporta-se como outros agentes, incluindo a permissão do registro explícito de plugins

Page 89: O que esperar do Zend Framework 2

Usando LazyLoadingBroker

$broker->registerSpec('url', array($request, $router));$broker->registerSpecs(array('url' => array($request, $router),));if (!$broker->hasPlugin('url')) {// sem especificação!}$plugins = $broker->getRegisteredPlugins(); // array('url')$url = $broker->load('url'); // Com $request, $router é injetado

Page 90: O que esperar do Zend Framework 2

Usando LazyLoadingBroker via Configuração

use Zend\View\HelperBroker;$config = array('specs' => array('url' => array($request, $router),),);$broker = new HelperBroker($config);$url= $broker->load('url'); // Com $request, $router é injetado

Page 91: O que esperar do Zend Framework 2

E ainda tem mais!

Page 92: O que esperar do Zend Framework 2

Novos Componentes

Page 93: O que esperar do Zend Framework 2

E Componentes Poderosos!

Page 94: O que esperar do Zend Framework 2

Novos Componentes

Zend\EventManager Zend\Di

Page 95: O que esperar do Zend Framework 2

EventManager

Page 96: O que esperar do Zend Framework 2

O Problema

Como nós introduzimos pontos de log/debug no código do framework?

Como nós permitimos que os usuários introduzam caching sem necessidade de estender o código do framework?

Como nós permitimos que os usuários introduzam validação, filtragem, verificações de controle de acesso, etc., sem necessariamente estender o código do framework?

Page 97: O que esperar do Zend Framework 2

O Problema

Como permitirmos que os usuários manipulem a ordem na qual plugins, filtros de interceptação, eventos, etc., são disparados.

Como nós podemos prover ferramentas para o código do usuário trabalhe em prol das questões anteriores?

Page 98: O que esperar do Zend Framework 2

Solução: Programação Orientada a Aspectos

O código define vários “aspectos” que podem ser interessantes observar e/ou anexar a partir de um consumidor.

Basicamente, todas as soluções que examinaremos podem ser usadas para implementar POA em um código base.

www.fgsl.eti.br

Palestras

Page 99: O que esperar do Zend Framework 2

Requisitos

Projeto que seja razoavelmente fácil de entender.

Permitir anexar manipuladores de forma estática ou por instância, preferencialmente de ambas as formas.

Preferencialmente enquanto reter o estado não-global ou permitir sobrescrita.

Permitir interrupção da execução Permitir a priorização de manipuladores

Page 100: O que esperar do Zend Framework 2

Requisitos

Projeto que seja razoavelmente fácil de entender.

Permitir anexar manipuladores de forma estática ou por instância, preferencialmente de ambas as formas.

Preferencialmente enquanto reter o estado não-global ou permitir sobrescrita.

Permitir interrupção da execução Permitir a priorização de manipuladores

Page 101: O que esperar do Zend Framework 2

Requisitos

Previsibilidade de argumentos passados para manipuladores.

Habilidade de anexar a muitos componentes emissores de eventos de uma vez.

Page 102: O que esperar do Zend Framework 2

Solução: Observador de Sujeitos

Prós Simples de entender Interfaces SPL são bem conhecidas (mas

limitadas)

Contras Tipicamente, não pode interromper a execução de

observadores remanescentes Requer um sistema para cada componente e/ou

classe Tipicamente, sem habilidade para priorizar

manipuladores

Page 103: O que esperar do Zend Framework 2

Solução: Publicador/Sobrescritor de Eventos

Prós Sobrescrita de notificações arbitrárias Tipicamente por componente + uso global; em

muitas linguagens, um único agregador global Paradigma bem-conhecido na programação de

interfaces com o usuário (pense em Javascript) Tende a ser um Turing completo

Page 104: O que esperar do Zend Framework 2

Solução: Publicador/Sobrescritor de Eventos (PubSub)

Contras Frequentemente, precisa testar o evento fornecido

para garantir que você pode manipulá-lo. Uso global implica em agregação estática e/ou

dependências estáticas. … mas o uso por componente implica em um

boilerplate para compor em cada classe se ele for usado.

Tipicamente, sem habilidade para priorizar manipuladores.

Falaremos mais sobre isso mais tarde...

Page 105: O que esperar do Zend Framework 2

Pausa para esclarecimento

boilerplate é o termo usado para descrever seções de código que foram incluídas em muitos lugares com pouca ou nenhuma alteração.

Page 106: O que esperar do Zend Framework 2

Solução: SignalSlots

Prós Conceito bem conhecido nos círculos de Ciência da

Computação O código emite sinais, que são interceptados por

slots (vulgos manipuladores) Tipicamente, compõe um gerenciador de sinais em

uma classe, mas pode ser integrado com um gerenciador global também

Geralmente tem algumas habilidades para priorizar manipuladores

Page 107: O que esperar do Zend Framework 2

Solução: SignalSlots

Contras Esse palavreado não é bem conhecido entre

programadores PHP. Argumentos irão variar entre sinais. Os mesmos problemas com composição por classe

e uso estático como vemos em sistemas de eventos.

Page 108: O que esperar do Zend Framework 2

Filtros de Interceptação

Prós Similar às soluções anteriores, exceto que cada

manipulador recebe a cadeia de filtros como um argumento, e é responsável por chamar o próximo na cadeia.

Frequentemente, o “trabalho” inteiro de um método é simplesmente um executar um filtro.

Dependendo do projeto, pode permitir acesso global/estático.

Page 109: O que esperar do Zend Framework 2

Filtros de Interceptação

Contras Algumas vezes é difícil acompanhar fluxos de

trabalho complexos. Os mesmos problemas com composição por classe

e uso estático como vemos em sistemas de evento. É fácil esquecer de invocar o próximo filtro na

cadeia. Tipicamente, sem habilidade de priorizar filtros.

Page 110: O que esperar do Zend Framework 2

Mas qual a

solução afinal?

Page 111: O que esperar do Zend Framework 2

Nenhuma!

Page 112: O que esperar do Zend Framework 2

Todas!

Page 113: O que esperar do Zend Framework 2

Linka

Ma-Ti Kwame

Wheeler

Gi

Co m

bina

ção

de P

oder

es

Page 114: O que esperar do Zend Framework 2

ZF2: EventManager Component

A cereja do bolo de cada solução, PubSub, SignalSlot, e Filtros de Interceptação, para prover uma solução compreensiva.

Não pode resolver completamente os problemas de composição/uso estático.

Nós podemos resolver o problema da composição no PHP 5.4 com Traits.

Há formas elegantes de manipular o uso estático.

Page 115: O que esperar do Zend Framework 2

Interface EventCollection

namespace Zend\EventManager;use Zend\Stdlib\CallbackHandler;interface EventCollection{public function trigger($event, $context, $argv = array());public function triggerUntil($event, $context, $argv, $callback);public function attach($event, $callback, $priority = 1);public function detach(CallbackHandler $handle);public function getEvents();public function getHandlers($event);public function clearHandlers($event);}

Page 116: O que esperar do Zend Framework 2

Disparando Eventos

use Zend\EventManager\EventManager;$events = new EventManager();$events->trigger($eventName, $object, $params);/* Onde: * - $eventName é o nome do evento; geralmente o nome do evento atual** - $object é o objeto que está disparando o evento* - $params são os parâmetros que o manipulador pode precisar para ter acesso,geralmente os argumentos do método**/

Page 117: O que esperar do Zend Framework 2

CallbackHandler

$handler = $events->attach('algum-evento', function($e) use ($log) {$event= $e->getName();$context = get_class($e->getTarget());$params = json_encode($e->getParams());$log->info(sprintf("%s: %s: %s", $event, $context, $params));});

Page 118: O que esperar do Zend Framework 2

Callback Handler com Prioridade

$handler = $events->attach('algum-evento', function($e) use ($log) {/* o mesmo que o anterior */}, 100); // Priorize! (números altos ganham)

Page 119: O que esperar do Zend Framework 2

Interrompendo a Execução: Testando Resultados

$results = $events->triggerUntil('algum-evento', $o, $argv,function($result) {return ($result instanceof SomeType);});if ($results->stopped()) {return $results->last();}

Page 120: O que esperar do Zend Framework 2

Interrompendo a Execução: via Manipuladores

$events->attach('algum-evento', function($e) {$result = new Result;$e->stopPropagation(true);return $result;});$results = $events->trigger('algum-evento', $object, $params);if ($results->stopped()) {return $results->last();}

Page 121: O que esperar do Zend Framework 2

Compondo um EventManageruse Zend\EventManager\EventCollection as Events,Zend\EventManager\EventManager;class Arisia{protected $events;public function events(Events $events = null){if (null !== $events) {$this->events = $events;} elseif (null === $this->events) {$this->events = new EventManager(__CLASS__);}return $this->events;}public function doSomething($param1, $param2){$params = compact('param1', 'param2');$this->events()->trigger(__FUNCTION__, $this, $params);}}

Page 122: O que esperar do Zend Framework 2

Usando um Trait!

use Zend\EventManager\EventCollection as Events,Zend\EventManager\EventManager;trait Eventful{public function events(Events $events = null){if (null !== $events) {$this->events = $events;} elseif (null === $this->events) {$this->events = new EventManager(__CLASS__);}return $this->events;}}class Arisia{use Eventful;protected $events;}

Page 123: O que esperar do Zend Framework 2

Conectando Manipuladores Estaticamente

use Zend\EventManager\StaticEventManager;$events = StaticEventManager::getInstance();$events->connect('Arisia', 'algum-evento', function ($e) {/* ... */});

Page 124: O que esperar do Zend Framework 2

Recomendações

Nomeie seus eventos usando __FUNCTION__ Se disparar múltiplos eventos no mesmo método,

sufixe com um “.(pre|pos|etc.)”

Forneça para o construtor do EventManager tanto o nome da classe quanto um ou mais nomes de “serviços”, para fazer anexações estáticas mais semânticas.

Isso permite que um único callback ouça muitos componentes!

Page 125: O que esperar do Zend Framework 2

Injeção de Dependência (DI)

Page 126: O que esperar do Zend Framework 2

O Que é Injeção de Dependência?

Muito simples: definir modos de passar dependências para dentro de um objeto.

namespace Tomarre\Helper;class Url{public function __construct(Request $request){$this->request = $request;}public function setRouter(Router $router){$this->router = $router;}}

Page 127: O que esperar do Zend Framework 2

Então porque as pessoas tem medo disso?

Porque elas não fazem isso. Elas temem os Conteineres de Injeção de

Dependência.

Page 128: O que esperar do Zend Framework 2

O Que é um Conteiner de Injeção de Dependência

Colocando de forma simples:

Um grafo de objetos para mapear relações de dependência entre

objetos.

Page 129: O que esperar do Zend Framework 2

Grafos

Page 130: O que esperar do Zend Framework 2

Novamente, por que as pessoas tem medo disso?

Porque parece mágica!

Page 131: O que esperar do Zend Framework 2

Objeto com Dependências

namespace Tomarre\Helper;class Url{public function __construct(Request $request){$this->request = $request;}public function setRouter(Router $router){$this->router = $router;}}

Page 132: O que esperar do Zend Framework 2

Outro Objeto com Dependências

namespace mwop\Mvc;class Router{public function addRoute(Route $route){$this->routes->push($route);}}

Page 133: O que esperar do Zend Framework 2

Agarrando um Objeto e Usando-o

$urlHelper = $di->get('url-helper');echo $url->generate('/css/site.css');echo $url->generate(array('id' => $id), array('name' => 'blog'));

Page 134: O que esperar do Zend Framework 2

As Questões

Como eu posso estar certo se eu tenho minhas dependências?

Você as define explicitamente. Você recupera o objeto via conteiner, o que garante

que as definições são usadas.

Onde eu defino essas coisas? Programaticamente, via configuração, ou usando

uma ferramenta.

Page 135: O que esperar do Zend Framework 2

As Questões

Se eu chamar $object = new Salaak(), como eu forço o uso de diferentes dependências?

Chamar new não usa o conteiner. Na verdade, nada força você a usá-lo!

Page 136: O que esperar do Zend Framework 2

Por que usar um?

Se a instanciação de seus objetos não está debaixo de seu controle direto (por exemplo, controladores), como você retém controle sobre suas dependências?

Acesso a dados diferente baseado no ambiente da aplicação.

Substituição de implementações mock/stub durante o teste.

Page 137: O que esperar do Zend Framework 2

Abordagem ZF2

Padronizar em uma interface de localizador de serviços.

Prover uma solução DI performática, e integrá-la dentro de um localizador de serviços.

Prover ferramentas para auxiliar na criação de definições de DI durante o desenvolvimento.

Page 138: O que esperar do Zend Framework 2

Interface para Localizador de Serviços

namespace Zend\Di;interface ServiceLocation{public function set($name, $service);public function get($name, array $params = null);}

Page 139: O que esperar do Zend Framework 2

Interface para Injetor de Dependências

namespace Zend\Di;interface DependencyInjection{public function get($name, array $params = null);public function newInstance($name, array $params = null);public function setDefinitions($definitions);public function setDefinition(DependencyDefinition $definition, $serviceName = null);public function setAlias($alias, $serviceName);public function getDefinitions();public function getAliases();}

Page 140: O que esperar do Zend Framework 2

Definiçõesnamespace Zend\Di;interface DependencyDefinition{public function __construct($className);public function getClass();public function setConstructorCallback($callback);public function getConstructorCallback();public function hasConstructorCallback();public function setParam($name, $value);public function setParams(array $params);public function setParamMap(array $map);public function getParams();public function setShared($flag = true);public function isShared();public function addTag($tag);public function addTags(array $tags);public function getTags();public function hasTag($tag);public function addMethodCall($name, array $args);public function getMethodCalls();}

Page 141: O que esperar do Zend Framework 2

Referências

namespace Zend\Di;interface DependencyReference{public function __construct($serviceName);public function getServiceName();}

Page 142: O que esperar do Zend Framework 2

Definição de Classe

use Zend\Di\Definition,Zend\Di\Reference;$mongo = new Definition('Mongo');$mongoDB = new Definition('MongoDB');$mongoDB->setParam('conn', new Reference('mongo'))->setParam('name', 'test');$coll = new Definition('MongoCollection');$coll->setParam('db', new Reference('mongodb'))->setParam('name', 'resource');$di->setDefinitions(array('mongo'=> $mongo,'mongodb' => $mongoDB,'resource' => $coll,));$resource = $di->get('resource');

Page 143: O que esperar do Zend Framework 2

Injeção por Modificador

use Zend\Di\Definition,Zend\Di\Reference;$service = new Definition('mwop\Service\Resources');$service->addMethod('setResource', array(new Reference('resource')));$di->setDefinition('resources', $service);$resources = $di->get('resources');

Page 144: O que esperar do Zend Framework 2

Fazendo mais Rápido

Especificar mapas de parâmetros de construtor em definições.

Gerar localizadores de serviço a partir de um conteiner DI.

Page 145: O que esperar do Zend Framework 2

Mapas de Parâmetros

$mongoDB->setParam('conn', new Reference('mongo'))->setParam('name', 'test')->setParamMap(array('conn' => 0,'name' => 1,));// Garante que os parâmetros estão em ordem, sem precisar// recorrer à API de reflexão

Page 146: O que esperar do Zend Framework 2

Gerando um Localizador de Serviços a partir de DI

use Zend\Di\ContainerBuilder as DiBuilder;$builder = new DiBuilder($injector);$builder->setContainerClass('AppContext');$container = $builder->getCodeGenerator(__DIR__ . '/../application/AppContext.php'); // Retorna uma instância de Zend\CodeGenerator\Php\PhpFile$container->write(); // Grava no disco

Page 147: O que esperar do Zend Framework 2

Exemplo de um localizador gerado

use Zend\Di\DependencyInjectionContainer;class AppContext extends DependencyInjectionContainer{public function get($name, array $params = array()){switch ($name) {case 'request':case 'Zend\Http\Request':return $this->getZendHttpRequest();default:return parent::get($name, $params);}}public function getZendHttpRequest(){if (isset($this->services['Zend\Http\Request'])) {return $this->services['Zend\Http\Request'];}$object = new \Zend\Http\Request();$this->services['Zend\Http\Request'] = $object;return $object;}}

Page 148: O que esperar do Zend Framework 2

Usando um localizador gerado

$context = new AppContext();$request = $context->get('request');// O mesmo que usar um localizador de serviços ou um conteiner DI!

Page 149: O que esperar do Zend Framework 2

Fazendo mais simples ainda

Use arquivos de configuração Você pode usar qualquer formato suportado

por Zend\Config: INI JSON XML YAML

Page 150: O que esperar do Zend Framework 2

Exemplo de configuração com JSON

{"production": { "definitions": [{ "class": "Mongo" },{ "class": "MongoDB","params": {"conn": {"__reference": "mongocxn"},"name": "mwoptest"},"param_map": { "conn": 0, "name": 1 }},{ "class": "MongoCollection","params": {"db": {"__reference": "MongoDB"},"name": "entries"},"param_map": { "db": 0, "name": 1 }}], "aliases": {"mongocxn": "Mongo","mongo-collection-entries": "MongoCollection"}}}

Page 151: O que esperar do Zend Framework 2

Quais são os casos de uso no ZF2?

Um grandão.

Tirar os controladores MVC do conteiner

Page 152: O que esperar do Zend Framework 2

Um Controlador de Ação

namespace Blog\Controller;class Entry implements Dispatchable{public function setResource(Resource $resource){$this->resource = $resource;}public function dispatch(Request $request, Response $response =null){/* ... */$entry = $this->resource->get($id);/* ... */}}

Page 153: O que esperar do Zend Framework 2

O Controlador Frontal

class FrontController implements Dispatchable{public function __construct(DependencyInjection $di){$this->di = $di;}public function dispatch(Request $request, Response $response =null){/* ... */$controller = $this->di->get($controllerName);$result = $controller->dispatch($request, $response);/* ... */}}

Page 154: O que esperar do Zend Framework 2

Benefícios de usar DI deste modo

Performance Desacoplamento de código Simplificação do código do controlador

Page 155: O que esperar do Zend Framework 2

E vem mais por aí

Compilação na primeira execução. Ferramentas para vasculhar classes ou

namespaces para construir definições. Injeção de interface. … e mais coisas legais.

Page 156: O que esperar do Zend Framework 2

Padrões MVC

Page 157: O que esperar do Zend Framework 2

Padrões MVC

Page 158: O que esperar do Zend Framework 2

Os Problemas

Como os controladores obtém dependências? Como nós acomodamos diferentes padrões de

controladores? E se se nós quisermos uma seleção de ações mais

apurada, baseada em outros dados no ambiente de requisição?

E se quisermos passar argumentos para nomes de ações, ou argumentos pré-validados?

E se nós não gostarmos do sufixo “Action” nos métodos acionadores?

E se...

Page 159: O que esperar do Zend Framework 2

Os Problemas

Como nós podemos melhorar o uso de componentes do servidor dentro do MVC?

Como nós podemos fazer o MVC mais performático?

Page 160: O que esperar do Zend Framework 2

A estrutura básica de uma aplicação web é a de um

ciclo de vida Requisição/Resposta

Page 161: O que esperar do Zend Framework 2

A interface Dispatchable

namespace Zend\Stdlib;interface Dispatchable{public function dispatch(Request $request, Response $response = null);}

Page 162: O que esperar do Zend Framework 2

Requisição e Resposta

Tanto a Requisição quanto a Resposta simplesmente agregam metadados e conteúdo.

A Resposta também tem a habilidade de enviar a si mesma.

Variantes específicas de HTTP serão o núcleo do MVC.

Para prover conveniência em torno de variáveis superglobais, cookies e tarefas comuns tais como determinar os cabeçalhos Accept e Content-Type.

Page 163: O que esperar do Zend Framework 2

Qualquer Dispatchable pode anexar ao MVC

Dispatchable é simplesmente uma formalização do padrão de projeto Command. Controladores Servidores Qualquer coisa que você sonhar! Apenas

implemente Dispatchable!

Page 164: O que esperar do Zend Framework 2

Um protótipo simples de um Controlador Frontal

public function dispatch(Request $request, Response $response = null){$params = compact('request', 'response');$this->events()->trigger(__FUNCTION__ . '.route.pre', $this,$params);$result = $this->getRouter()->route($request);if (!$result) {$result = array('controller' => 'page', 'page' => 404);}$params['routing'] = (object) $result;$this->events()->trigger(__FUNCTION__ . '.route.post', $params);$controller = $this->di->get($params['routing']->controller);if (!$controller instanceof Dispatchable) {$controller = new NotFoundController();}$result = $controller->dispatch($request, $response);$params['__RESULT__'] = $result;$this->events()->trigger(__FUNCTION__ . '.dispatch.post',$params);return $response;}

Page 165: O que esperar do Zend Framework 2

Contexto Temporal

Quando esta apresentação foi finalizada, o último release do Zend Framework 1 era o 1.11.11 e o Zend Framework 2 estava na versão 2.0.0beta1.

Page 166: O que esperar do Zend Framework 2

Mais informações

http://framework.zend.com https://github.com/zendframework/zf2 www.fgsl.eti.br

Aguarde... treinamentos de arquitetura, migração, e desenvolvimento.

Pra quem quer sair na frente, Mão na Massa MVC Zend Framework 2!

Coming soon 2012!