SlideShare una empresa de Scribd logo
1 de 166
Descargar para leer sin conexión
Existe uma coisa que um programador PHP
não pode ter...




                            MEDO!
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.
Advertência

   Esta apresentação não visa saciar sua sede de
    conhecimento, mas deixar você sedento por
    ele.
O que esperar do Zend Framework 2


  Flávio Gomes da
  Silva Lisboa

 www.fgsl.eti.br




                    @fgsl
Inspirador   Inspirado
                                    Desde 2008 capacitando
                                    profissionais em Zend
                                    Framework

           @eminetto
                         @fgsl
ESGOTADO




    ESGOTADO
Uma Breve História do ZF




      Flávio Gomes da Silva Lisboa
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
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.
1.5.0 – Março de 2008

   Primeiro release menor
   Zend_Form
   Zend_Layout
   Sistema de view helper ciente
    do layout
             Layout content



              View content
1.6.0 – Setembro de 2008

   Integração com Dojo
   Zend_Test: extensão PHPUnit
    para controladores
   Action helper ContextSwitch

         HTML          JSON




         XML
1.7.0 – Novembro de 2008

   Suporte à AMF
   Melhorias de performance
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
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
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”
1.11.0 – Novembro de 2010

   Suporte mobile via
    Zend_Http_UserAgent
   API SimpleCloud via
    Zend_Cloud
Arquitetura
Arquitetura
Arquitetura
Flexibilidade
Liberdade de Escolha
E daqui vamos para onde?
Revolução
Inevitável
Junte-se ou morra!
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.”
Evolução
O foco do Zend Framework 2.0 é na melhoria da
consistência e performance.
Código Explícito

   Não é isto:
                class SoraniknatuController
                extends Zend_Controller_Action
                {
                public function useTheRingAction()
                {
                $this->view->object = 'imagination';
                }
                }




    Onde isso             Quando
                                              E os
      está                ocorre a
                                            layouts?
    definido?          renderização?
Mágica
   ou
Bruxaria?
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.
Melhorias incrementais
Passos de Bebê

   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
Reescrever somente onde faz
          sentido
Mudanças na Infraestrutura
Namespaces
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
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.
Exemplo de Namespace


namespace ZendEventManager;

use ZendStdlibCallbackHandler;

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

namespace ZendMvc;

use ZendStdlibDispatchable,
ZendDiServiceLocator as Locator;

class FrontController implements Dispatchable
{
public function __construct(Locator $locator)
{
$this->serviceLocator = $locator;
}
}
Recomendação para Migração

Importe classes com o comando
use em vez de fazer chamadas
com require_once em seu
código!
Importando Classes
use Zend_Controller_Action as Controller;

class PowerController extends Controller
{                                           ZF1
}

             Como ficará:
use ZendControllerAction as Controller;

class PowerController extends Controller
{                                           ZF2
}
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.
Exemplos de Nomeação




namespace ZendEventManager;

class EventManager implements EventCollection
{

}
Interfaces
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
Exemplo de Interfaces




namespace ZendSession;

use Traversable, ArrayAccess, Serializable, Countable;

interface Storage extends Traversable, ArrayAccess, Serializable,
Countable
{

}
Implementação Concreta


namespace ZendSessionStorage;

use ArrayObject,
ZendSessionStorage,
ZendSessionException;

class ArrayStorage extends ArrayObject implements Storage
{
/* ... */
}
Exceções
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
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
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
Definições de Exceção
                                   namespace ZendEventManager;

                                   interface Exception
                                   {

                                   }

namespace ZendEventManagerException;

use ZendEventManagerException;

class InvalidArgumentException extends InvalidArgumentException
implements Exception
{

}
Capturando Exceções

namespace ZendEventManagerException;

use ZendEventManagerException;

try {
$events->trigger('dom.quixote', $object);
} catch (InvalidArgumentException $e) {
} catch (Exception $e) {
} catch (InvalidArgumentException $e) {
} catch (Exception $e) {
}
Autocarregamento
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.
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
Autocarregamento estilo ZF1

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


                  EX
                     EM
                          PL
                            O
Autocarregamento
        Namespace/Prefixo ZF2

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



                       EX
                          EM
                               PL
                                 O
Autocarregamento com Mapas de
           Classes

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


  require_once 'Zend/Loader/ClassMapAutoloader.php';
  $loader = new ZendLoaderClassMapAutoloader();
  $loader->registerAutoloadMap(__DIR__ .
  '/../library/.classmap.php');
  $loader->register();
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:
prompt> cd your/library
 
prompt> php /path/to/classmap_generator.php -w



   A execução desse script cria o Mapa de
    Classes em .classmap.php
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.
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
Exemplo de Fábrica de
      Autocarregadores
require_once 'Zend/Loader/AutoloaderFactory.php';
use ZendLoaderAutoloaderFactory;
AutoloaderFactory::factory(array(
'ZendLoaderClassMapAutoloader' => array(
__DIR__ . '/../library/.classmap.php',
__DIR__ . '/../application/.classmap.php',
),
'ZendLoaderStandardAutoloader' => array(
'namespaces' => array(
'Zend' => __DIR__ . '/../library/Zend',
),
'fallback_autoloader' => true,
),
));
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!
Carregamento de Plugins
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
Plugins
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
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
Interface de Localização de
          Plugins


   namespace ZendLoader;
   interface ShortNameLocator
   {
   public function isLoaded($name);
   public function getClassName($name);
   public function load($name);
   }
Interface de Agente de Plugins

namespace ZendLoader;
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();
}
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
Implementação do Localizador de
           Plugins
    namespace ZendView;
    use ZendLoaderPluginClassLoader;
    class HelperLoader extends PluginClassLoader
    {
    /**
      * @var array Pre-aliased view helpers
      */
    protected $plugins = array(
    'action'
    => 'ZendViewHelperAction',
    'base_url' => 'ZendViewHelperBaseUrl',
    /* ... */
    );
    }
Implementação do Agente de
           Plugins
class HelperBroker extends PluginBroker
{
protected $defaultClassLoader = 'ZendViewHelperLoader';
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;
}
}
Compondo um Agente
use ZendViewHelperLoader;
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);
}
}
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
Definindo Mapas Estáticos


use ZendViewHelperLoader;
HelperLoader::addStaticMap(array(
'url'
=> 'KilowogHelperUrl',
'base_url' => 'ProjectHelperBaseUrl',
));
$loader = new HelperLoader();
$class = $loader->load('url'); // "KilowogHelperUrl"
Passando Mapas via
           Configuração


use ZendViewHelperLoader;
$config = array(
'url'
=> 'KilowogHelperUrl',
'base_url' => 'ProjectHelperBaseUrl',
);
$loader = new HelperLoader($config);
$class = $loader->load('url'); // "KilowogHelperUrl"
Passando Mapas para Mapas!

 use ZendViewHelperLoader,
 ZendLoaderPluginClassLoader;
 class HelperMap extends PluginClassLoader
 {
 protected $plugins = array(
 'url'
 => 'KilowogHelperUrl',
 'base_url' => 'ProjectHelperBaseUrl',
 );
 }
 $helpers = new HelperMap();
 $loader = new HelperLoader($helpers);
 $class
 = $loader->load('url'); // "KilowogHelperUrl"
Estendendo Carregadores
use ZendViewHelperLoader;
class HelperMap extends HelperLoader
{
public function __construct($options = null)
{
// Adiciona e/ou sobrescreve o mapa do
HelperLoader
$this->registerPlugins(array(
'url'
=> 'KilowogHelperUrl',
'base_url' => 'ProjectHelperBaseUrl',
));
parent::__construct($options);
}
}
$helpers = new HelperMap();
$class
= $loader->load('url'); // "KilowogHelperUrl"
Passando Mapas via Agente

use ZendViewHelperBroker;
$broker = new HelperBroker(array(
'class_loader' => array(
'class'
=> 'HelperMap',
'options' => array(
'base_url' => 'AppHelperBaseUrl',
),
),
));
$plugin = $broker->load('base_url'); // "AppHelperBaseUrl"
Criando Mapas Manualmente


use ZendViewHelperLoader;
$loader = new HelperLoader();
$loader->registerPlugin('url', 'KilowogHelperUrl')
->registerPlugins(array(
'base_url' => 'ProjectHelperBaseUrl',
));
$class = $loader->load('url'); // "KilowogHelperUrl"
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
Registrando um Plugin com o
          Agente

use KilowogHelperUrl;
// 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
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
    ZendLoaderLazyLoadingBroker
LazyLoadingBroker Interface


namespace ZendLoader;
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);
}
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
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
Usando LazyLoadingBroker via
         Configuração

use ZendViewHelperBroker;
$config = array(
'specs' => array(
'url' => array($request, $router),
),
);
$broker = new HelperBroker($config);
$url
= $broker->load('url'); // Com $request, $router é
injetado
E ainda tem mais!
Novos Componentes
E Componentes Poderosos!
Novos Componentes

   ZendEventManager
   ZendDi
EventManager
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?
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?
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
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
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
Requisitos

   Previsibilidade de argumentos passados para
    manipuladores.
   Habilidade de anexar a muitos componentes
    emissores de eventos de uma vez.
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
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
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...
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.
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
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.
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.
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.
Mas
 qual a
solução
 afinal?
Nenhuma!
Todas!
Combinação




                               de Poderes
                                            Linka
Wheeler




 Gi                    Ma-Ti                    Kwame
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.
Interface EventCollection

namespace ZendEventManager;
use ZendStdlibCallbackHandler;
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);
}
Disparando Eventos

use ZendEventManagerEventManager;
$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
*
*/
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));
});
Callback Handler com Prioridade



$handler = $events->attach('algum-evento', function($e) use
($log) {
/* o mesmo que o anterior */
}, 100); // Priorize! (números altos ganham)
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();
}
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();
}
Compondo um EventManager
use ZendEventManagerEventCollection as Events,
ZendEventManagerEventManager;
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);
}
}
Usando um Trait!
use ZendEventManagerEventCollection as Events,
ZendEventManagerEventManager;
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;
}
Conectando Manipuladores
       Estaticamente


use ZendEventManagerStaticEventManager;
$events = StaticEventManager::getInstance();
$events->connect('Arisia', 'algum-evento', function
($e) {
/* ... */
});
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!
Injeção de Dependência (DI)
O Que é Injeção de Dependência?

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

       namespace TomarreHelper;
       class Url
       {
       public function __construct(Request $request)
       {
       $this->request = $request;
       }
       public function setRouter(Router $router)
       {
       $this->router = $router;
       }
       }
Então porque as pessoas tem
            medo disso?
   Porque elas não fazem isso.
   Elas temem os Conteineres de Injeção de
    Dependência.
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.
Grafos
Novamente, por que as pessoas
     tem medo disso?

   Porque parece mágica!
Objeto com Dependências

namespace TomarreHelper;
class Url
{
public function __construct(Request $request)
{
$this->request = $request;
}
public function setRouter(Router $router)
{
$this->router = $router;
}
}
Outro Objeto com Dependências


     namespace mwopMvc;
     class Router
     {
     public function addRoute(Route $route)
     {
     $this->routes->push($route);
     }
     }
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'));
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.
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!
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.
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.
Interface para Localizador de
           Serviços


namespace ZendDi;
interface ServiceLocation
{
public function set($name, $service);
public function get($name, array $params = null);
}
Interface para Injetor de
            Dependências

namespace ZendDi;
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();
}
Definições
namespace ZendDi;
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();
}
Referências



namespace ZendDi;
interface DependencyReference
{
public function __construct($serviceName);
public function getServiceName();
}
Definição de Classe
use ZendDiDefinition,
ZendDiReference;
$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');
Injeção por Modificador


use ZendDiDefinition,
ZendDiReference;
$service = new Definition('mwopServiceResources');
$service->addMethod('setResource', array(
new Reference('resource')
));
$di->setDefinition('resources', $service);
$resources = $di->get('resources');
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.
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
Gerando um Localizador de
       Serviços a partir de DI


use ZendDiContainerBuilder as DiBuilder;
$builder = new DiBuilder($injector);
$builder->setContainerClass('AppContext');
$container = $builder->getCodeGenerator(
__DIR__ . '/../application/AppContext.php'
); // Retorna uma instância de ZendCodeGeneratorPhpPhpFile
$container->write(); // Grava no disco
Exemplo de um localizador
           gerado
use ZendDiDependencyInjectionContainer;
class AppContext extends DependencyInjectionContainer
{
public function get($name, array $params = array())
{
switch ($name) {
case 'request':
case 'ZendHttpRequest':
return $this->getZendHttpRequest();
default:
return parent::get($name, $params);
}
}
public function getZendHttpRequest()
{
if (isset($this->services['ZendHttpRequest'])) {
return $this->services['ZendHttpRequest'];
}
$object = new ZendHttpRequest();
$this->services['ZendHttpRequest'] = $object;
return $object;
}
}
Usando um localizador gerado



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

   Use arquivos de configuração
   Você pode usar qualquer formato suportado
    por ZendConfig:
       INI
       JSON
       XML
       YAML
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"
}
}
}
Quais são os casos de uso no
                ZF2?
   Um grandão.

Tirar os controladores
  MVC do conteiner
Um Controlador de Ação
namespace BlogController;
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);
/* ... */
}
}
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);
/* ... */
}
}
Benefícios de usar DI deste modo

   Performance
   Desacoplamento de código
   Simplificação do código do controlador
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.
Padrões MVC
Padrões MVC
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...
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?
A estrutura básica de uma
aplicação web é a de um
       ciclo de vida
  Requisição/Resposta
A interface Dispatchable


namespace ZendStdlib;
interface Dispatchable
{
public function dispatch(
Request $request, Response $response = null
);
}
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.
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!
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;
}
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.
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!

Más contenido relacionado

La actualidad más candente

Introdução a CDI e como utilizá-la em aplicações reais
Introdução a CDI e como utilizá-la em aplicações reaisIntrodução a CDI e como utilizá-la em aplicações reais
Introdução a CDI e como utilizá-la em aplicações reaisMichel Graciano
 
ZF2 básico : Desenvolvendo um Blog com o Zend Framework 2
ZF2 básico : Desenvolvendo um Blog com o Zend Framework 2ZF2 básico : Desenvolvendo um Blog com o Zend Framework 2
ZF2 básico : Desenvolvendo um Blog com o Zend Framework 2Cezar Souza
 
Sistemas Distribuídos - Comunicação Distribuída - EJB
Sistemas Distribuídos - Comunicação Distribuída - EJBSistemas Distribuídos - Comunicação Distribuída - EJB
Sistemas Distribuídos - Comunicação Distribuída - EJBAdriano Teixeira de Souza
 
Demoiselle Behave - Parte 2
Demoiselle Behave - Parte 2Demoiselle Behave - Parte 2
Demoiselle Behave - Parte 2Vanderson Silva
 
Como construir aplicações gráficas e applets
Como construir aplicações gráficas e appletsComo construir aplicações gráficas e applets
Como construir aplicações gráficas e appletsDenis L Presciliano
 
Demoiselle Behave - Parte 3
Demoiselle Behave - Parte 3Demoiselle Behave - Parte 3
Demoiselle Behave - Parte 3Vanderson Silva
 
Introdução à Programação em Java - Aula 1 (PT-PT)
Introdução à Programação em Java - Aula 1 (PT-PT)Introdução à Programação em Java - Aula 1 (PT-PT)
Introdução à Programação em Java - Aula 1 (PT-PT)Manoel Campos da Silva Filho
 
Zend Framework 1.11
Zend Framework 1.11Zend Framework 1.11
Zend Framework 1.11Cezar Souza
 
Introdução a Linguagem Java
Introdução a Linguagem JavaIntrodução a Linguagem Java
Introdução a Linguagem JavaUFPA
 
Demoiselle Behave - Parte 4
Demoiselle Behave - Parte 4Demoiselle Behave - Parte 4
Demoiselle Behave - Parte 4Vanderson Silva
 
Sistemas Distribuídos - Comunicação Distribuída - EJB (JBoss 7)
Sistemas Distribuídos - Comunicação Distribuída - EJB (JBoss 7)Sistemas Distribuídos - Comunicação Distribuída - EJB (JBoss 7)
Sistemas Distribuídos - Comunicação Distribuída - EJB (JBoss 7)Adriano Teixeira de Souza
 
Artigo Automação de testes funcionais com Demoiselle Behave
Artigo Automação de testes funcionais com Demoiselle BehaveArtigo Automação de testes funcionais com Demoiselle Behave
Artigo Automação de testes funcionais com Demoiselle BehaveJulian Cesar
 
Programação Orientada a Objetos com Java
Programação Orientada a Objetos com JavaProgramação Orientada a Objetos com Java
Programação Orientada a Objetos com JavaÁlvaro Farias Pinheiro
 
Selenium Workshop
Selenium WorkshopSelenium Workshop
Selenium Workshopcathoderay
 
Apostila de Fundamentos Java
Apostila de Fundamentos JavaApostila de Fundamentos Java
Apostila de Fundamentos JavaMarcio Marinho
 
Webservices e Computação em Nuvem com PHP
Webservices e Computação em Nuvem com PHPWebservices e Computação em Nuvem com PHP
Webservices e Computação em Nuvem com PHPFlávio Lisboa
 
A arquitetura modular do Java 9
A arquitetura modular do Java 9A arquitetura modular do Java 9
A arquitetura modular do Java 9Helder da Rocha
 
Apresentação Java, SOA, MICROSERVICE, HTTP, HTTPS, VERSIONAMENTO DE CONTRATO,
Apresentação Java, SOA, MICROSERVICE, HTTP, HTTPS, VERSIONAMENTO DE CONTRATO, Apresentação Java, SOA, MICROSERVICE, HTTP, HTTPS, VERSIONAMENTO DE CONTRATO,
Apresentação Java, SOA, MICROSERVICE, HTTP, HTTPS, VERSIONAMENTO DE CONTRATO, Vinicius Pulgatti
 

La actualidad más candente (20)

Introdução a CDI e como utilizá-la em aplicações reais
Introdução a CDI e como utilizá-la em aplicações reaisIntrodução a CDI e como utilizá-la em aplicações reais
Introdução a CDI e como utilizá-la em aplicações reais
 
ZF2 básico : Desenvolvendo um Blog com o Zend Framework 2
ZF2 básico : Desenvolvendo um Blog com o Zend Framework 2ZF2 básico : Desenvolvendo um Blog com o Zend Framework 2
ZF2 básico : Desenvolvendo um Blog com o Zend Framework 2
 
Zephir
ZephirZephir
Zephir
 
Sistemas Distribuídos - Comunicação Distribuída - EJB
Sistemas Distribuídos - Comunicação Distribuída - EJBSistemas Distribuídos - Comunicação Distribuída - EJB
Sistemas Distribuídos - Comunicação Distribuída - EJB
 
Demoiselle Behave - Parte 2
Demoiselle Behave - Parte 2Demoiselle Behave - Parte 2
Demoiselle Behave - Parte 2
 
Como construir aplicações gráficas e applets
Como construir aplicações gráficas e appletsComo construir aplicações gráficas e applets
Como construir aplicações gráficas e applets
 
Demoiselle Behave - Parte 3
Demoiselle Behave - Parte 3Demoiselle Behave - Parte 3
Demoiselle Behave - Parte 3
 
Introdução à Programação em Java - Aula 1 (PT-PT)
Introdução à Programação em Java - Aula 1 (PT-PT)Introdução à Programação em Java - Aula 1 (PT-PT)
Introdução à Programação em Java - Aula 1 (PT-PT)
 
Zend Framework 1.11
Zend Framework 1.11Zend Framework 1.11
Zend Framework 1.11
 
Introdução a Linguagem Java
Introdução a Linguagem JavaIntrodução a Linguagem Java
Introdução a Linguagem Java
 
Demoiselle Behave - Parte 4
Demoiselle Behave - Parte 4Demoiselle Behave - Parte 4
Demoiselle Behave - Parte 4
 
Sistemas Distribuídos - Comunicação Distribuída - EJB (JBoss 7)
Sistemas Distribuídos - Comunicação Distribuída - EJB (JBoss 7)Sistemas Distribuídos - Comunicação Distribuída - EJB (JBoss 7)
Sistemas Distribuídos - Comunicação Distribuída - EJB (JBoss 7)
 
Artigo Automação de testes funcionais com Demoiselle Behave
Artigo Automação de testes funcionais com Demoiselle BehaveArtigo Automação de testes funcionais com Demoiselle Behave
Artigo Automação de testes funcionais com Demoiselle Behave
 
Programação Orientada a Objetos com Java
Programação Orientada a Objetos com JavaProgramação Orientada a Objetos com Java
Programação Orientada a Objetos com Java
 
Selenium Workshop
Selenium WorkshopSelenium Workshop
Selenium Workshop
 
Apostila de Fundamentos Java
Apostila de Fundamentos JavaApostila de Fundamentos Java
Apostila de Fundamentos Java
 
servlet-introducao
servlet-introducaoservlet-introducao
servlet-introducao
 
Webservices e Computação em Nuvem com PHP
Webservices e Computação em Nuvem com PHPWebservices e Computação em Nuvem com PHP
Webservices e Computação em Nuvem com PHP
 
A arquitetura modular do Java 9
A arquitetura modular do Java 9A arquitetura modular do Java 9
A arquitetura modular do Java 9
 
Apresentação Java, SOA, MICROSERVICE, HTTP, HTTPS, VERSIONAMENTO DE CONTRATO,
Apresentação Java, SOA, MICROSERVICE, HTTP, HTTPS, VERSIONAMENTO DE CONTRATO, Apresentação Java, SOA, MICROSERVICE, HTTP, HTTPS, VERSIONAMENTO DE CONTRATO,
Apresentação Java, SOA, MICROSERVICE, HTTP, HTTPS, VERSIONAMENTO DE CONTRATO,
 

Destacado

Desenvolvimento Web com CakePHP
Desenvolvimento Web com CakePHPDesenvolvimento Web com CakePHP
Desenvolvimento Web com CakePHPSérgio Vilar
 
Workshop: WebSockets com HTML 5 & PHP - Gustavo Ciello
Workshop: WebSockets com HTML 5 & PHP - Gustavo CielloWorkshop: WebSockets com HTML 5 & PHP - Gustavo Ciello
Workshop: WebSockets com HTML 5 & PHP - Gustavo CielloTchelinux
 
PHP 5.3 - Estruturas de Controle
PHP 5.3 - Estruturas de ControlePHP 5.3 - Estruturas de Controle
PHP 5.3 - Estruturas de ControleGeorge Mendonça
 
HTML5 for PHP Developers - IPC
HTML5 for PHP Developers - IPCHTML5 for PHP Developers - IPC
HTML5 for PHP Developers - IPCMayflower GmbH
 
Classroom Objects: PowerPoint Activities
Classroom Objects: PowerPoint ActivitiesClassroom Objects: PowerPoint Activities
Classroom Objects: PowerPoint ActivitiesA. Simoes
 
PHP Powerpoint -- Teach PHP with this
PHP Powerpoint -- Teach PHP with thisPHP Powerpoint -- Teach PHP with this
PHP Powerpoint -- Teach PHP with thisIan Macali
 

Destacado (10)

SQL Devlopment for 10 ppt
SQL Devlopment for 10 pptSQL Devlopment for 10 ppt
SQL Devlopment for 10 ppt
 
PHP- Introduction to Object Oriented PHP
PHP-  Introduction to Object Oriented PHPPHP-  Introduction to Object Oriented PHP
PHP- Introduction to Object Oriented PHP
 
Desenvolvimento Web com CakePHP
Desenvolvimento Web com CakePHPDesenvolvimento Web com CakePHP
Desenvolvimento Web com CakePHP
 
Workshop: WebSockets com HTML 5 & PHP - Gustavo Ciello
Workshop: WebSockets com HTML 5 & PHP - Gustavo CielloWorkshop: WebSockets com HTML 5 & PHP - Gustavo Ciello
Workshop: WebSockets com HTML 5 & PHP - Gustavo Ciello
 
PHP 5.3 - Estruturas de Controle
PHP 5.3 - Estruturas de ControlePHP 5.3 - Estruturas de Controle
PHP 5.3 - Estruturas de Controle
 
Css Ppt
Css PptCss Ppt
Css Ppt
 
HTML5 for PHP Developers - IPC
HTML5 for PHP Developers - IPCHTML5 for PHP Developers - IPC
HTML5 for PHP Developers - IPC
 
Classroom Objects: PowerPoint Activities
Classroom Objects: PowerPoint ActivitiesClassroom Objects: PowerPoint Activities
Classroom Objects: PowerPoint Activities
 
Php mysql ppt
Php mysql pptPhp mysql ppt
Php mysql ppt
 
PHP Powerpoint -- Teach PHP with this
PHP Powerpoint -- Teach PHP with thisPHP Powerpoint -- Teach PHP with this
PHP Powerpoint -- Teach PHP with this
 

Similar a O que esperar do Zend Framework 2

Introdução ao Zend Framework 2
Introdução ao Zend Framework 2Introdução ao Zend Framework 2
Introdução ao Zend Framework 2Elton Minetto
 
Desmistificando o Framework da Zend
Desmistificando o Framework da ZendDesmistificando o Framework da Zend
Desmistificando o Framework da ZendDomingos Teruel
 
Desfrutando os Componentes do Zend Framework
Desfrutando os Componentes do Zend FrameworkDesfrutando os Componentes do Zend Framework
Desfrutando os Componentes do Zend FrameworkFernando Geraldo Mantoan
 
Apostila Zend Framework
Apostila Zend FrameworkApostila Zend Framework
Apostila Zend FrameworkFernando Palma
 
O que esperar do Zend Framework 3
O que esperar do Zend Framework 3O que esperar do Zend Framework 3
O que esperar do Zend Framework 3Flávio Lisboa
 
ZF Básico - 1. Introdução
ZF Básico - 1. IntroduçãoZF Básico - 1. Introdução
ZF Básico - 1. IntroduçãoMarcos Bezerra
 
Framework PHP Zend e MVC
Framework PHP Zend e MVCFramework PHP Zend e MVC
Framework PHP Zend e MVCEduardo Greco
 
Introdução ao zend framework
Introdução ao zend frameworkIntrodução ao zend framework
Introdução ao zend frameworkMarcos Oliveira
 
Certificação Zend Framework
Certificação Zend FrameworkCertificação Zend Framework
Certificação Zend FrameworkJaime Neto
 
Zend Framework - PHPSP - 2009
Zend Framework - PHPSP - 2009Zend Framework - PHPSP - 2009
Zend Framework - PHPSP - 2009silva.edgar
 
Phpjedi 090307090434-phpapp01 2
Phpjedi 090307090434-phpapp01 2Phpjedi 090307090434-phpapp01 2
Phpjedi 090307090434-phpapp01 2PrinceGuru MS
 
PHP like a super hero
PHP like a super heroPHP like a super hero
PHP like a super heroElton Minetto
 
Gerenciando aspectos e eventos com Zend Framework 2
Gerenciando aspectos e eventos com Zend Framework 2Gerenciando aspectos e eventos com Zend Framework 2
Gerenciando aspectos e eventos com Zend Framework 2Flávio Lisboa
 
Curso de Introdução - PHP Zend Framework
Curso de Introdução - PHP Zend FrameworkCurso de Introdução - PHP Zend Framework
Curso de Introdução - PHP Zend FrameworkEvandro Klimpel Balmant
 
Desenvolvendo em Zend Framework: Ênfase no Zend_Db
Desenvolvendo em Zend Framework: Ênfase no Zend_DbDesenvolvendo em Zend Framework: Ênfase no Zend_Db
Desenvolvendo em Zend Framework: Ênfase no Zend_DbFlávio Lisboa
 
Palestra Zend Framework CISL 2012 - ZF no Governo Federal
Palestra Zend Framework CISL 2012 - ZF no Governo FederalPalestra Zend Framework CISL 2012 - ZF no Governo Federal
Palestra Zend Framework CISL 2012 - ZF no Governo FederalFlávio Lisboa
 

Similar a O que esperar do Zend Framework 2 (20)

Introdução ao Zend Framework 2
Introdução ao Zend Framework 2Introdução ao Zend Framework 2
Introdução ao Zend Framework 2
 
Desmistificando o Framework da Zend
Desmistificando o Framework da ZendDesmistificando o Framework da Zend
Desmistificando o Framework da Zend
 
Desfrutando os Componentes do Zend Framework
Desfrutando os Componentes do Zend FrameworkDesfrutando os Componentes do Zend Framework
Desfrutando os Componentes do Zend Framework
 
Apostila Zend Framework
Apostila Zend FrameworkApostila Zend Framework
Apostila Zend Framework
 
O que esperar do Zend Framework 3
O que esperar do Zend Framework 3O que esperar do Zend Framework 3
O que esperar do Zend Framework 3
 
ZF Básico - 1. Introdução
ZF Básico - 1. IntroduçãoZF Básico - 1. Introdução
ZF Básico - 1. Introdução
 
Framework PHP Zend e MVC
Framework PHP Zend e MVCFramework PHP Zend e MVC
Framework PHP Zend e MVC
 
Cakephp 2.0 - O que mudou
Cakephp 2.0 - O que mudouCakephp 2.0 - O que mudou
Cakephp 2.0 - O que mudou
 
Introdução ao zend framework
Introdução ao zend frameworkIntrodução ao zend framework
Introdução ao zend framework
 
Certificação Zend Framework
Certificação Zend FrameworkCertificação Zend Framework
Certificação Zend Framework
 
Zend Framework - PHPSP - 2009
Zend Framework - PHPSP - 2009Zend Framework - PHPSP - 2009
Zend Framework - PHPSP - 2009
 
Phpjedi 090307090434-phpapp01 2
Phpjedi 090307090434-phpapp01 2Phpjedi 090307090434-phpapp01 2
Phpjedi 090307090434-phpapp01 2
 
PHP like a super hero
PHP like a super heroPHP like a super hero
PHP like a super hero
 
Aop Aspect J 1.5.4
Aop Aspect J 1.5.4Aop Aspect J 1.5.4
Aop Aspect J 1.5.4
 
Java Seminar
Java SeminarJava Seminar
Java Seminar
 
Gerenciando aspectos e eventos com Zend Framework 2
Gerenciando aspectos e eventos com Zend Framework 2Gerenciando aspectos e eventos com Zend Framework 2
Gerenciando aspectos e eventos com Zend Framework 2
 
Curso de Introdução - PHP Zend Framework
Curso de Introdução - PHP Zend FrameworkCurso de Introdução - PHP Zend Framework
Curso de Introdução - PHP Zend Framework
 
Desenvolvendo em Zend Framework: Ênfase no Zend_Db
Desenvolvendo em Zend Framework: Ênfase no Zend_DbDesenvolvendo em Zend Framework: Ênfase no Zend_Db
Desenvolvendo em Zend Framework: Ênfase no Zend_Db
 
Palestra Zend Framework no Governo Federal
Palestra Zend Framework  no Governo FederalPalestra Zend Framework  no Governo Federal
Palestra Zend Framework no Governo Federal
 
Palestra Zend Framework CISL 2012 - ZF no Governo Federal
Palestra Zend Framework CISL 2012 - ZF no Governo FederalPalestra Zend Framework CISL 2012 - ZF no Governo Federal
Palestra Zend Framework CISL 2012 - ZF no Governo Federal
 

Más de Flávio Lisboa

Criando testes integrados de APIs com PHP
Criando testes integrados de APIs com PHPCriando testes integrados de APIs com PHP
Criando testes integrados de APIs com PHPFlávio Lisboa
 
Cooperativas de Software Livre: Uma comparação entre Brasil e Argentina
Cooperativas de Software Livre: Uma comparação entre Brasil e ArgentinaCooperativas de Software Livre: Uma comparação entre Brasil e Argentina
Cooperativas de Software Livre: Uma comparação entre Brasil e ArgentinaFlávio Lisboa
 
Aprenda a afiar suas garras com Laminas
Aprenda a afiar suas garras com LaminasAprenda a afiar suas garras com Laminas
Aprenda a afiar suas garras com LaminasFlávio Lisboa
 
Ciência e software livre: desenvolvendo com método
Ciência e software livre: desenvolvendo com métodoCiência e software livre: desenvolvendo com método
Ciência e software livre: desenvolvendo com métodoFlávio Lisboa
 
Turbinando microsserviços em PHP
Turbinando microsserviços em PHPTurbinando microsserviços em PHP
Turbinando microsserviços em PHPFlávio Lisboa
 
O que esperar do framework Laminas
O que esperar do framework LaminasO que esperar do framework Laminas
O que esperar do framework LaminasFlávio Lisboa
 
PHP Conference Brazil - What can we expect about framework Laminas?
PHP Conference Brazil - What can we expect about framework Laminas?PHP Conference Brazil - What can we expect about framework Laminas?
PHP Conference Brazil - What can we expect about framework Laminas?Flávio Lisboa
 
Algoritmos Genéticos em PHP - PHP Conference Brasil 2019
Algoritmos Genéticos em PHP - PHP Conference Brasil 2019Algoritmos Genéticos em PHP - PHP Conference Brasil 2019
Algoritmos Genéticos em PHP - PHP Conference Brasil 2019Flávio Lisboa
 
Criando microsserviços em PHP
Criando microsserviços em PHPCriando microsserviços em PHP
Criando microsserviços em PHPFlávio Lisboa
 
Como se tornar o pior programador PHP do mundo
Como se tornar o pior programador PHP do mundoComo se tornar o pior programador PHP do mundo
Como se tornar o pior programador PHP do mundoFlávio Lisboa
 
A demanda da santa entrega Batman: bugs e gargalos em aplicações PHP
A demanda da santa entrega Batman: bugs e gargalos em aplicações PHPA demanda da santa entrega Batman: bugs e gargalos em aplicações PHP
A demanda da santa entrega Batman: bugs e gargalos em aplicações PHPFlávio Lisboa
 
Comunicação e padrões em código aberto: quando convergente e divergente cooperam
Comunicação e padrões em código aberto: quando convergente e divergente cooperamComunicação e padrões em código aberto: quando convergente e divergente cooperam
Comunicação e padrões em código aberto: quando convergente e divergente cooperamFlávio Lisboa
 
Criação de robôs em PHP para raspagem de dados
Criação de robôs em PHP para raspagem de dadosCriação de robôs em PHP para raspagem de dados
Criação de robôs em PHP para raspagem de dadosFlávio Lisboa
 
Estudo de Caso: Utilização de PHP no Serviço Federal de Processamento de Dados
Estudo de Caso: Utilização de PHP no Serviço Federal de Processamento de DadosEstudo de Caso: Utilização de PHP no Serviço Federal de Processamento de Dados
Estudo de Caso: Utilização de PHP no Serviço Federal de Processamento de DadosFlávio Lisboa
 
Arquitetura PHP para um mundo orientado a microsserviços
Arquitetura PHP para um mundo orientado a microsserviçosArquitetura PHP para um mundo orientado a microsserviços
Arquitetura PHP para um mundo orientado a microsserviçosFlávio Lisboa
 
Semeando Liberdade: Como (e onde) o software livre inclui as pessoas
Semeando Liberdade: Como (e onde) o software livre inclui as pessoasSemeando Liberdade: Como (e onde) o software livre inclui as pessoas
Semeando Liberdade: Como (e onde) o software livre inclui as pessoasFlávio Lisboa
 
O que é programação de computadores
O que é programação de computadoresO que é programação de computadores
O que é programação de computadoresFlávio Lisboa
 
Economia em rede (comunidade)
Economia em rede (comunidade)Economia em rede (comunidade)
Economia em rede (comunidade)Flávio Lisboa
 
Aplicações Corporativas em PHP (CRM e ERP)
Aplicações Corporativas em PHP (CRM e ERP)Aplicações Corporativas em PHP (CRM e ERP)
Aplicações Corporativas em PHP (CRM e ERP)Flávio Lisboa
 

Más de Flávio Lisboa (20)

Criando testes integrados de APIs com PHP
Criando testes integrados de APIs com PHPCriando testes integrados de APIs com PHP
Criando testes integrados de APIs com PHP
 
Cooperativas de Software Livre: Uma comparação entre Brasil e Argentina
Cooperativas de Software Livre: Uma comparação entre Brasil e ArgentinaCooperativas de Software Livre: Uma comparação entre Brasil e Argentina
Cooperativas de Software Livre: Uma comparação entre Brasil e Argentina
 
Aprenda a afiar suas garras com Laminas
Aprenda a afiar suas garras com LaminasAprenda a afiar suas garras com Laminas
Aprenda a afiar suas garras com Laminas
 
Ciência e software livre: desenvolvendo com método
Ciência e software livre: desenvolvendo com métodoCiência e software livre: desenvolvendo com método
Ciência e software livre: desenvolvendo com método
 
Turbinando microsserviços em PHP
Turbinando microsserviços em PHPTurbinando microsserviços em PHP
Turbinando microsserviços em PHP
 
O que esperar do framework Laminas
O que esperar do framework LaminasO que esperar do framework Laminas
O que esperar do framework Laminas
 
PHP Conference Brazil - What can we expect about framework Laminas?
PHP Conference Brazil - What can we expect about framework Laminas?PHP Conference Brazil - What can we expect about framework Laminas?
PHP Conference Brazil - What can we expect about framework Laminas?
 
Algoritmos Genéticos em PHP - PHP Conference Brasil 2019
Algoritmos Genéticos em PHP - PHP Conference Brasil 2019Algoritmos Genéticos em PHP - PHP Conference Brasil 2019
Algoritmos Genéticos em PHP - PHP Conference Brasil 2019
 
Criando microsserviços em PHP
Criando microsserviços em PHPCriando microsserviços em PHP
Criando microsserviços em PHP
 
Como se tornar o pior programador PHP do mundo
Como se tornar o pior programador PHP do mundoComo se tornar o pior programador PHP do mundo
Como se tornar o pior programador PHP do mundo
 
A demanda da santa entrega Batman: bugs e gargalos em aplicações PHP
A demanda da santa entrega Batman: bugs e gargalos em aplicações PHPA demanda da santa entrega Batman: bugs e gargalos em aplicações PHP
A demanda da santa entrega Batman: bugs e gargalos em aplicações PHP
 
Comunicação e padrões em código aberto: quando convergente e divergente cooperam
Comunicação e padrões em código aberto: quando convergente e divergente cooperamComunicação e padrões em código aberto: quando convergente e divergente cooperam
Comunicação e padrões em código aberto: quando convergente e divergente cooperam
 
Criação de robôs em PHP para raspagem de dados
Criação de robôs em PHP para raspagem de dadosCriação de robôs em PHP para raspagem de dados
Criação de robôs em PHP para raspagem de dados
 
Amanhecer esmeralda
Amanhecer esmeraldaAmanhecer esmeralda
Amanhecer esmeralda
 
Estudo de Caso: Utilização de PHP no Serviço Federal de Processamento de Dados
Estudo de Caso: Utilização de PHP no Serviço Federal de Processamento de DadosEstudo de Caso: Utilização de PHP no Serviço Federal de Processamento de Dados
Estudo de Caso: Utilização de PHP no Serviço Federal de Processamento de Dados
 
Arquitetura PHP para um mundo orientado a microsserviços
Arquitetura PHP para um mundo orientado a microsserviçosArquitetura PHP para um mundo orientado a microsserviços
Arquitetura PHP para um mundo orientado a microsserviços
 
Semeando Liberdade: Como (e onde) o software livre inclui as pessoas
Semeando Liberdade: Como (e onde) o software livre inclui as pessoasSemeando Liberdade: Como (e onde) o software livre inclui as pessoas
Semeando Liberdade: Como (e onde) o software livre inclui as pessoas
 
O que é programação de computadores
O que é programação de computadoresO que é programação de computadores
O que é programação de computadores
 
Economia em rede (comunidade)
Economia em rede (comunidade)Economia em rede (comunidade)
Economia em rede (comunidade)
 
Aplicações Corporativas em PHP (CRM e ERP)
Aplicações Corporativas em PHP (CRM e ERP)Aplicações Corporativas em PHP (CRM e ERP)
Aplicações Corporativas em PHP (CRM e ERP)
 

O que esperar do Zend Framework 2

  • 1. Existe uma coisa que um programador PHP não pode ter... MEDO!
  • 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.
  • 3. Advertência  Esta apresentação não visa saciar sua sede de conhecimento, mas deixar você sedento por ele.
  • 4. O que esperar do Zend Framework 2 Flávio Gomes da Silva Lisboa www.fgsl.eti.br @fgsl
  • 5.
  • 6. Inspirador Inspirado Desde 2008 capacitando profissionais em Zend Framework @eminetto @fgsl ESGOTADO ESGOTADO
  • 7. Uma Breve História do ZF Flávio Gomes da Silva Lisboa
  • 8. 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
  • 9. 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.
  • 10. 1.5.0 – Março de 2008  Primeiro release menor  Zend_Form  Zend_Layout  Sistema de view helper ciente do layout Layout content View content
  • 11. 1.6.0 – Setembro de 2008  Integração com Dojo  Zend_Test: extensão PHPUnit para controladores  Action helper ContextSwitch HTML JSON XML
  • 12. 1.7.0 – Novembro de 2008  Suporte à AMF  Melhorias de performance
  • 13. 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
  • 14. 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
  • 15. 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”
  • 16. 1.11.0 – Novembro de 2010  Suporte mobile via Zend_Http_UserAgent  API SimpleCloud via Zend_Cloud
  • 22. E daqui vamos para onde?
  • 26. 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.”
  • 28. O foco do Zend Framework 2.0 é na melhoria da consistência e performance.
  • 29. Código Explícito  Não é isto: class SoraniknatuController extends Zend_Controller_Action { public function useTheRingAction() { $this->view->object = 'imagination'; } } Onde isso Quando E os está ocorre a layouts? definido? renderização?
  • 30. Mágica ou Bruxaria?
  • 31. 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.
  • 33. Passos de Bebê  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
  • 34. Reescrever somente onde faz sentido
  • 37. 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
  • 38. 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.
  • 39. Exemplo de Namespace namespace ZendEventManager; use ZendStdlibCallbackHandler; class EventManager implements EventCollection { /* ... */ }
  • 40. Usando Apelidos namespace ZendMvc; use ZendStdlibDispatchable, ZendDiServiceLocator as Locator; class FrontController implements Dispatchable { public function __construct(Locator $locator) { $this->serviceLocator = $locator; } }
  • 41. Recomendação para Migração Importe classes com o comando use em vez de fazer chamadas com require_once em seu código!
  • 42. Importando Classes use Zend_Controller_Action as Controller; class PowerController extends Controller { ZF1 } Como ficará: use ZendControllerAction as Controller; class PowerController extends Controller { ZF2 }
  • 43. 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.
  • 44. Exemplos de Nomeação namespace ZendEventManager; class EventManager implements EventCollection { }
  • 46. 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
  • 47. Exemplo de Interfaces namespace ZendSession; use Traversable, ArrayAccess, Serializable, Countable; interface Storage extends Traversable, ArrayAccess, Serializable, Countable { }
  • 48. Implementação Concreta namespace ZendSessionStorage; use ArrayObject, ZendSessionStorage, ZendSessionException; class ArrayStorage extends ArrayObject implements Storage { /* ... */ }
  • 50. 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
  • 51. 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
  • 52. 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
  • 53. Definições de Exceção namespace ZendEventManager; interface Exception { } namespace ZendEventManagerException; use ZendEventManagerException; class InvalidArgumentException extends InvalidArgumentException implements Exception { }
  • 54. Capturando Exceções namespace ZendEventManagerException; use ZendEventManagerException; try { $events->trigger('dom.quixote', $object); } catch (InvalidArgumentException $e) { } catch (Exception $e) { } catch (InvalidArgumentException $e) { } catch (Exception $e) { }
  • 56. 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.
  • 57. 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
  • 58. Autocarregamento estilo ZF1 require_once 'Zend/Loader/StandardAutoloader.php'; $loader = new ZendLoaderStandardAutoloader(array( 'fallback_autoloader' => true, )); $loader->register(); EX EM PL O
  • 59. Autocarregamento Namespace/Prefixo ZF2 require_once 'Zend/Loader/StandardAutoloader.php'; $loader = new ZendLoaderStandardAutoloader(); $loader->registerNamespace('My', __DIR__ . '/../library/My') ->registerPrefix('Fgsl_', __DIR__ . '/../library/Fgsl'); $loader->register(); EX EM PL O
  • 60. Autocarregamento com Mapas de Classes return array( 'GreenLanternHal' => __DIR__ . '/Lantern/Hal.php', ); require_once 'Zend/Loader/ClassMapAutoloader.php'; $loader = new ZendLoaderClassMapAutoloader(); $loader->registerAutoloadMap(__DIR__ . '/../library/.classmap.php'); $loader->register();
  • 61. 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: prompt> cd your/library  prompt> php /path/to/classmap_generator.php -w   A execução desse script cria o Mapa de Classes em .classmap.php
  • 62. 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.
  • 63. 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
  • 64. Exemplo de Fábrica de Autocarregadores require_once 'Zend/Loader/AutoloaderFactory.php'; use ZendLoaderAutoloaderFactory; AutoloaderFactory::factory(array( 'ZendLoaderClassMapAutoloader' => array( __DIR__ . '/../library/.classmap.php', __DIR__ . '/../application/.classmap.php', ), 'ZendLoaderStandardAutoloader' => array( 'namespaces' => array( 'Zend' => __DIR__ . '/../library/Zend', ), 'fallback_autoloader' => true, ), ));
  • 65. 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!
  • 67. 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
  • 69. 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
  • 70. 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
  • 71. Interface de Localização de Plugins namespace ZendLoader; interface ShortNameLocator { public function isLoaded($name); public function getClassName($name); public function load($name); }
  • 72. Interface de Agente de Plugins namespace ZendLoader; 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(); }
  • 73. 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
  • 74. Implementação do Localizador de Plugins namespace ZendView; use ZendLoaderPluginClassLoader; class HelperLoader extends PluginClassLoader { /** * @var array Pre-aliased view helpers */ protected $plugins = array( 'action' => 'ZendViewHelperAction', 'base_url' => 'ZendViewHelperBaseUrl', /* ... */ ); }
  • 75. Implementação do Agente de Plugins class HelperBroker extends PluginBroker { protected $defaultClassLoader = 'ZendViewHelperLoader'; 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; } }
  • 76. Compondo um Agente use ZendViewHelperLoader; 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); } }
  • 77. 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
  • 78. Definindo Mapas Estáticos use ZendViewHelperLoader; HelperLoader::addStaticMap(array( 'url' => 'KilowogHelperUrl', 'base_url' => 'ProjectHelperBaseUrl', )); $loader = new HelperLoader(); $class = $loader->load('url'); // "KilowogHelperUrl"
  • 79. Passando Mapas via Configuração use ZendViewHelperLoader; $config = array( 'url' => 'KilowogHelperUrl', 'base_url' => 'ProjectHelperBaseUrl', ); $loader = new HelperLoader($config); $class = $loader->load('url'); // "KilowogHelperUrl"
  • 80. Passando Mapas para Mapas! use ZendViewHelperLoader, ZendLoaderPluginClassLoader; class HelperMap extends PluginClassLoader { protected $plugins = array( 'url' => 'KilowogHelperUrl', 'base_url' => 'ProjectHelperBaseUrl', ); } $helpers = new HelperMap(); $loader = new HelperLoader($helpers); $class = $loader->load('url'); // "KilowogHelperUrl"
  • 81. Estendendo Carregadores use ZendViewHelperLoader; class HelperMap extends HelperLoader { public function __construct($options = null) { // Adiciona e/ou sobrescreve o mapa do HelperLoader $this->registerPlugins(array( 'url' => 'KilowogHelperUrl', 'base_url' => 'ProjectHelperBaseUrl', )); parent::__construct($options); } } $helpers = new HelperMap(); $class = $loader->load('url'); // "KilowogHelperUrl"
  • 82. Passando Mapas via Agente use ZendViewHelperBroker; $broker = new HelperBroker(array( 'class_loader' => array( 'class' => 'HelperMap', 'options' => array( 'base_url' => 'AppHelperBaseUrl', ), ), )); $plugin = $broker->load('base_url'); // "AppHelperBaseUrl"
  • 83. Criando Mapas Manualmente use ZendViewHelperLoader; $loader = new HelperLoader(); $loader->registerPlugin('url', 'KilowogHelperUrl') ->registerPlugins(array( 'base_url' => 'ProjectHelperBaseUrl', )); $class = $loader->load('url'); // "KilowogHelperUrl"
  • 84. 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
  • 85. Registrando um Plugin com o Agente use KilowogHelperUrl; // 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
  • 86. 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 ZendLoaderLazyLoadingBroker
  • 87. LazyLoadingBroker Interface namespace ZendLoader; 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); }
  • 88. 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
  • 89. 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
  • 90. Usando LazyLoadingBroker via Configuração use ZendViewHelperBroker; $config = array( 'specs' => array( 'url' => array($request, $router), ), ); $broker = new HelperBroker($config); $url = $broker->load('url'); // Com $request, $router é injetado
  • 91. E ainda tem mais!
  • 94. Novos Componentes  ZendEventManager  ZendDi
  • 96. 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?
  • 97. 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?
  • 98. 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
  • 99. 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
  • 100. 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
  • 101. Requisitos  Previsibilidade de argumentos passados para manipuladores.  Habilidade de anexar a muitos componentes emissores de eventos de uma vez.
  • 102. 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
  • 103. 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
  • 104. 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...
  • 105. 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.
  • 106. 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
  • 107. 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.
  • 108. 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.
  • 109. 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.
  • 112. Todas!
  • 113. Combinação de Poderes Linka Wheeler Gi Ma-Ti Kwame
  • 114. 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.
  • 115. Interface EventCollection namespace ZendEventManager; use ZendStdlibCallbackHandler; 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); }
  • 116. Disparando Eventos use ZendEventManagerEventManager; $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 * */
  • 117. 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)); });
  • 118. Callback Handler com Prioridade $handler = $events->attach('algum-evento', function($e) use ($log) { /* o mesmo que o anterior */ }, 100); // Priorize! (números altos ganham)
  • 119. 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(); }
  • 120. 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(); }
  • 121. Compondo um EventManager use ZendEventManagerEventCollection as Events, ZendEventManagerEventManager; 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); } }
  • 122. Usando um Trait! use ZendEventManagerEventCollection as Events, ZendEventManagerEventManager; 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; }
  • 123. Conectando Manipuladores Estaticamente use ZendEventManagerStaticEventManager; $events = StaticEventManager::getInstance(); $events->connect('Arisia', 'algum-evento', function ($e) { /* ... */ });
  • 124. 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!
  • 126. O Que é Injeção de Dependência?  Muito simples: definir modos de passar dependências para dentro de um objeto. namespace TomarreHelper; class Url { public function __construct(Request $request) { $this->request = $request; } public function setRouter(Router $router) { $this->router = $router; } }
  • 127. Então porque as pessoas tem medo disso?  Porque elas não fazem isso.  Elas temem os Conteineres de Injeção de Dependência.
  • 128. 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.
  • 129. Grafos
  • 130. Novamente, por que as pessoas tem medo disso? Porque parece mágica!
  • 131. Objeto com Dependências namespace TomarreHelper; class Url { public function __construct(Request $request) { $this->request = $request; } public function setRouter(Router $router) { $this->router = $router; } }
  • 132. Outro Objeto com Dependências namespace mwopMvc; class Router { public function addRoute(Route $route) { $this->routes->push($route); } }
  • 133. 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'));
  • 134. 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.
  • 135. 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!
  • 136. 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.
  • 137. 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.
  • 138. Interface para Localizador de Serviços namespace ZendDi; interface ServiceLocation { public function set($name, $service); public function get($name, array $params = null); }
  • 139. Interface para Injetor de Dependências namespace ZendDi; 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(); }
  • 140. Definições namespace ZendDi; 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(); }
  • 141. Referências namespace ZendDi; interface DependencyReference { public function __construct($serviceName); public function getServiceName(); }
  • 142. Definição de Classe use ZendDiDefinition, ZendDiReference; $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');
  • 143. Injeção por Modificador use ZendDiDefinition, ZendDiReference; $service = new Definition('mwopServiceResources'); $service->addMethod('setResource', array( new Reference('resource') )); $di->setDefinition('resources', $service); $resources = $di->get('resources');
  • 144. 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.
  • 145. 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
  • 146. Gerando um Localizador de Serviços a partir de DI use ZendDiContainerBuilder as DiBuilder; $builder = new DiBuilder($injector); $builder->setContainerClass('AppContext'); $container = $builder->getCodeGenerator( __DIR__ . '/../application/AppContext.php' ); // Retorna uma instância de ZendCodeGeneratorPhpPhpFile $container->write(); // Grava no disco
  • 147. Exemplo de um localizador gerado use ZendDiDependencyInjectionContainer; class AppContext extends DependencyInjectionContainer { public function get($name, array $params = array()) { switch ($name) { case 'request': case 'ZendHttpRequest': return $this->getZendHttpRequest(); default: return parent::get($name, $params); } } public function getZendHttpRequest() { if (isset($this->services['ZendHttpRequest'])) { return $this->services['ZendHttpRequest']; } $object = new ZendHttpRequest(); $this->services['ZendHttpRequest'] = $object; return $object; } }
  • 148. Usando um localizador gerado $context = new AppContext(); $request = $context->get('request'); // O mesmo que usar um localizador de serviços ou um conteiner DI!
  • 149. Fazendo mais simples ainda  Use arquivos de configuração  Você pode usar qualquer formato suportado por ZendConfig:  INI  JSON  XML  YAML
  • 150. 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" } } }
  • 151. Quais são os casos de uso no ZF2?  Um grandão. Tirar os controladores MVC do conteiner
  • 152. Um Controlador de Ação namespace BlogController; 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); /* ... */ } }
  • 153. 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); /* ... */ } }
  • 154. Benefícios de usar DI deste modo  Performance  Desacoplamento de código  Simplificação do código do controlador
  • 155. 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.
  • 158. 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...
  • 159. 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?
  • 160. A estrutura básica de uma aplicação web é a de um ciclo de vida Requisição/Resposta
  • 161. A interface Dispatchable namespace ZendStdlib; interface Dispatchable { public function dispatch( Request $request, Response $response = null ); }
  • 162. 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.
  • 163. 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!
  • 164. 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; }
  • 165. 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.
  • 166. 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!