ZendFramework: estruturar um novo projeto (parte 1)

Publicado: 22/01/2012 em Linux, Programação
Tags:, , ,

1. Um pouco de ideias (antes da parte prática)

O que se cria com um comando do Zend “create project” é apenas a estrutura do projeto, através de um módulo simples “default”. Nest post, mais adiante, iremos inclusive deletar esta estrutura inicial quando da criação dos novos módulos e controladores da nossa aplicação-exemplo.

Arquitetura da aplicação Zend

Toda solicitação feita ao ZendFramework possui basicamente 03 (três) elementos: Module, Controller e Action. Cada página da aplicação é conhecida como uma “action” (ação). Ações são agrupados dentro de “controllers” (controladores). Por exemplo, um certo controlador poderia ter ações como listar, arquivos e ver. E podem ser criados módulos para agrupar controladores. Vejamos as idéias conceituais básicas de cada um.

a) Módulo
Divisão lógica da aplicação, agrupando funcionalidades com objetivos distintos dos demais módulos. Os módulos devem ser utilizados para oferecer um nível maior de separação na aplicação e geralmente são usados para separar diferentes seções da aplicação e promover a reutilização de códigos. Cada módulo possui seu próprio diretório de controladores.
O Module (módulo) é o que modulariza a aplicação . Deve ser criado quando se precisa controlar várias seções distintas de uma aplicação. Um exemplo básico seria criar um módulo para a Área administrativa de uma aplicação e outro para a área Comercial.

Ao criar um projeto, o Zend cria automaticamente um module default. Caso se crie um novo Module, será necessário criar uma pasta para o novo default. O sistema MVC do Zend Framework suporta módulos para agrupamento de controladores.

b) Controller
O controller inicial de qualquer aplicação zend é o ‘index’. Ao criar um projeto, automaticamente o Zend cria o controller index. Os controllers controlam a lógica de negócio e o acesso aos dados presentes nos Actions.

Cada página da aplicação é conhecida como um Action (ação). As ações são agrupados dentro de controllers (controlador). Para o formato de URL http://novo_projeto.localhost/zf-tutorial/public/gerencia/produzir, o controlador é “Gerencia” e a ação é “produzir”. Assim é permitido agrupar ações relacionadas. Por exemplo, um controlador “Gerencia” poderia ter ações como listar, arquivos e ver.

c) Action
A camada de apresentação numa aplicação é aquela em que o usuário interage com o controller, por isto, e pelo fato do controller controlar primariamente actions que vão conter acesso a tudo o que existe no Zend e no MVC per si, a estrutura de arquivos é carregada a partir dos actions e não dos controllers em si. O action inicial de qualquer aplicação zend é o ‘index’. O action index não precisa ser chamado, pois o Zend o carrega automaticamente quando nenhum for passado.

2. Criar um projeto
Após ter instalado e configurado o ZendFramework (veja aqui), estamos prontos para começar tirar proveito do ZF. A maneira mais rápida de começar a usar a Zend_Application é utilizando os comandos disponíveis do Zend_tool. Vamos iniciar criando um novo projeto fazendo uso do Zend_tool. Abaixo é mostrado o comando para executar esta tarefa, e a resposta do sistema:

~/projetoszend$ zf create project novo_projeto
Creating project at ~/projetoszend/novo_projeto

OBS: sobre este comando veja mais detalhes em Create Your Project.
A ferramenta ZF criará um diretório chamado “novo_projeto” e preencherá com uma estrutura de diretório default do framework. Esta estrutura assume que o usuário tenha total controle sobre sua configuração do Apache, com a finalidade de manter a maior parte dos arquivos fora do diretório raiz do site. Após este comando, o usuário deverá ver os seguintes arquivos e diretórios:


novo_projeto/
 -rw-r--r--   .zfproject.xml
 drwxr-xr-x   library/
 drwxr-xr-x   application/
              -rw-r--r--   Bootstrap.php
              drwxr-xr-x   models/
              drwxr-xr-x   configs/
                           -rw-r--r--   application.ini
              drwxr-xr-x   controllers/
                           -rw-r--r--   ErrorController.php
                           -rw-r--r--   IndexController.php
              drwxr-xr-x   views/
                           drwxr-xr-x   helpers/
                           drwxr-xr-x   scripts/
                                        drwxr-xr-x   error/
                                                     -rw-r--r--   error.phtml
                                        drwxr-xr-x   index/
                                                     -rw-r--r-- index.phtml
 drwxr-xr-x   docs/
              -rw-r--r--   README.txt
 drwxr-xr-x   public/
              -rw-r--r--   .htaccess
              -rw-r--r--   index.php
 drwxr-xr-x   tests/
              -rw-r--r--   bootstrap.php
              -rw-r--r--   phpunit.xml
              drwxr-xr-x   library/
              drwxr-xr-x   application/
                           drwxr-xr-x   controllers/
                                        -rw-r--r--   IndexControllerTest.php

Estão vazias as pastas application/models/, application/views/helpers/, library/ e tests/library/ .

O diretório “application/” é onde o código da aplicação reside. Como pode-se ver, os diretórios para os arquivos model, view e controller da aplicação encontram-se separados. O diretório “public/” é o diretório de alcance publico. Isto é feito para que a maior parte dos arquivos da aplicação não sejam acessados diretamente pelo Apache e, portanto, estejam mais seguros. O controlador do Zend Frameworkʼs utiliza o Padrão de Software “Front Controller” e roteia todas as solicitações através de um único arquivo “public/index.php”.

Até aqui, se for acessada a página http://novo_projeto.localhost/ uma página em branco será mostrada no navegador.

Deve ser observado, em especial, que ao executar o comando acima, as seguintes operações especiais ocorreram:

  • criação do arquivo de Bootstrap em novo_projeto/application/Bootstrap.php;
  • criação do arquivo de configuração em novo_projeto/application/configs/application.ini, o qual é a configuração básica necessária para o Zend_Application;
  • criação do arquivo novo_projeto/public/index.php, o qual invoca o Zend_Application e faz o seu “dispatche”.

O arquivo de Bootstrap contém o seguinte conteúdo:

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
}

3. Fixar o ambiente da aplicação
Um aspecto que facilita muito o desenvolvimento software é ter do sistema informações de erros. Para isto deve ser alterado a definição do ambiente de produção para “development” que é realizada no arquivo “~/novo_projeto/public/index.php”. O default é “produção”, que omite as mensagens de erros. Edite o arquivo, e altere a linha que faz a definição do ambiente conforme abaixo:

defined('APPLICATION_ENV')
|| define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'development'));

4. Disponibilizar as bibliotecas do Zend

Copiar a pasta Zend(aproximadamente 23MB), que se encontra dentro de /opt/ZendFramework-1.11.11/library/ para a pasta novo_projeto/library (vide post de instalação do Zend):

~/novo_projeto/library$ cp -R /opt/ZendFramework-1.11.11/library/Zend/ .

Relativo a pasta library/ , a esturutura de pastas ficará assim:


~/novo_projeto/
-rw-r--r--   .zfproject.xml
drwxr-xr-x   library/
             drwxr-xr-x   Zend/

E o interior da pasta Zend/ conterá toda a biblioteca do ZendFramework.

Agora, ao acessar a página http://novo_projeto.localhost/ , será mostrado uma página com uma figura azul do emblema do ZendFramework. Esta página fora disponibilizada, como seria de esperar, por scripts (templates) dentro da pasta application/ . Ou seja, esta visualização se deve ao arquivo novo_projeto/application/views/scripts/index/index.phtml .

Observe que a página poderia ser acessada também por http://novo_projeto.localhost/default/index/index/ , que seria a mesma coisa. Para entender, o Zend trata estes parâmetros da seguinte forma (segundo a ordem da esquerda para a direita):
default: foi interpretado pelo Zend como o nome do MODULE;
index: foi interpretado pelo Zend como o nome do CONTROLLER;
index: foi interpretado pelo Zend como o nome da ACTION.

Até aqui não criamos nenhum MÓDULO, só existe o “default” criado pelo próprio Zend quando criamos inicialmente o novo_projeto. Se tivéssemos criado módulos, a estrutura das pastas teria a seguinte aparência:

Estrutura de pastas para o ZendFramework

Se houver necessidade de se utilizar quaisquer outras bibliotecas, elas também podem ser colocas nesta pasta.

5. Entendendo alguns aspectos do funcionamento do ZF

O arquivo index.php é o ponto de entrada para a aplicação e é utilizado para criar uma instância de “Zend_Application” para inicializar a aplicação e então executá-la. Este arquivo define duas constantes: APPLICATION_PATH e APPLICATION_ENV que definem o caminho para o diretório application/ e o modo do ambiente da aplicação. O padrão é definido como “production” no index.php, mas o usuário deve configurá-lo para “development” no arquivo .htaccess adicionando esta linha:
SetEnv APPLICATION_ENV development

O component “Zend_Application” é utilizado para iniciar a aplicação e está configurado para utilizar as diretivas de configuração do arquivo application/configs/application.ini. Este arquivo também é gerado automaticamente pelo ZF. Uma classe “Bootstrap” que extende “Zend_Application_Bootstrap_Bootstrap” é fornecida no arquivo “application/Bootstrap.php” que pode ser utilizada para executar qualquer código de iniciação específico.

O “application.ini”, que está armazenado no diretório “application/configs” é carregado utilizando o component “Zend_Config_In”. O “Zend_Config_Ini” entende o conceito de herança das seções que são definidas utilizando um ponto-duplo no nome da seção.
Por exemplo:
[staging : production]
Isto significa que a seção “staging” herda todas as configurações da seção “production”. A constante APPLICATION_ENV define qual seção é carregada. Obviamente, no meio do desenvolvimento, a seção “development” é melhor e quando estiver no servidor remoto, a seção “production” deve ser utilizada. Uma boa política é colocar todas as modificações que forem feitas no arquivo “application.ini” dentro da seção “production” para que todas as configurações carreguem as alterações que se fizerem necessárias.

Quanto a estrutura de módulos, controladores, actions e páginas, a estrutura a ser criada segue a arquitetura mostrada na figura abaixo.

Estrutura de projeto com módulos, controladores, actions e páginas.

Pela figura acima, pode-se ver que:

  • cada Página (arquivo .phtml) está associada a uma determinada Action
  • um conjunto de Actions está associado a um determinado Controlador
  • Um módulo encapsula um conjunto de Controladores

6. Tratamento de Erros
O Zend_Controller_Plugin_ErrorHandler fornece um plugin “drop-in” para o tratamento de exceções lançadas por sua aplicação, incluindo as resultantes dos controladores em falta ou ações. O plugin ErrorHandler é projetado para lidar com erros do tipo HTTP 404 (página em falta) e erros do tipo 500 (erro interno). Mas não pretende capturar exceções levantadas em outros plugins. Por padrão, Zend_Controller_Plugin_ErrorHandler redireciona para ErrorController:: errorAction() no módulo padrão. O redirecionamento pode ser feito para outros endereços. Veja como fazer isto e outros detalhes de tratamento de erros em Zend_Controller_Plugin_ErrorHandler.

Dois arquivos fundamentais para tratamento de erros são:

  • O script de visualização estará em application/views/scripts/error/error.phtml
  • O controlador “ErrorController” no módulo padrão, contendo um método errorAction()”, pode ser encontrado em application/controllers/ErrorController.php

Um erro pode ser simulado para ver o controlador de erro atuando. Digite na barra de endereço do navegador um endereço inexistente, como o exemplificado abaixo, para ver este tratamento de erro em ação:
http://novo_projeto.localhost/sdasdsa

7. Criar módulos

Abaixo mostramos a criação de dois módulos para novo_projeto e as respostas do framework:


~/novo_projeto$ zf create module tecnico
Creating the following module and artifacts:
~/novo_projeto/application/modules/tecnico/controllers
~/novo_projeto/application/modules/tecnico/models
~/novo_projeto/application/modules/tecnico/views
~/novo_projeto/application/modules/tecnico/views/scripts
~/novo_projeto/application/modules/tecnico/views/helpers
~/novo_projeto/application/modules/tecnico/views/filters
Added a key for path module directory to the application.ini file
Updating project profile '~/novo_projeto/.zfproject.xml'

~/novo_projeto$ zf create module admin
Creating the following module and artifacts:
~/novo_projeto/application/modules/admin/controllers
~/novo_projeto/application/modules/admin/models
~/novo_projeto/application/modules/admin/views
~/novo_projeto/application/modules/admin/views/scripts
~/novo_projeto/application/modules/admin/views/helpers
~/novo_projeto/application/modules/admin/views/filters
Added a key for path module directory to the application.ini file
Updating project profile '~/novo_projeto/.zfproject.xml'

Abaixo transcrevemos como ficou a estrutura de pastas com a criação dos dois módulos:


~/novo_projeto/application/
-rw-r--r--   Bootstrap.php
drwxr-xr-x   configs
drwxr-xr-x   models
drwxr-xr-x   modules
             drwxr-xr-x   tecnico
                          drwxr-xr-x   controllers
                          drwxr-xr-x   models
                          drwxr-xr-x   views
                                       drwxr-xr-x   filters
                                       drwxr-xr-x   helpers
                                       drwxr-xr-x   scripts
             drwxr-xr-x   admin
                          drwxr-xr-x   controllers
                          drwxr-xr-x   models
                          drwxr-xr-x   views
                                       drwxr-xr-x   filters
                                       drwxr-xr-x   helpers
                                       drwxr-xr-x   scripts

Observe que nas pastas internas de modules/ só existem pastas, mas não existem arquivos em nenhuma destas pastas.

8. Criar os controladores para os módulos
A lógica para criar um controller é a seguinte:

zf create controller NOME_DO_CONTROLLER 1 NOME_DO_MODULE

Agora criaremos os controladores associados ao módulo “tecnico”. Estão colocados abaixo os comandos e as respostas do framework:

~/novo_projeto$ zf create controller Gerencia 1 tecnico
Creating a controller at ~/novo_projeto/application/modules/tecnico/controllers/GerenciaController.php
Creating an index action method in controller Gerencia
Creating a view script for the index action method at ~/novo_projeto/application/modules/tecnico/views/scripts/gerencia/index.phtml
Updating project profile '~/novo_projeto/.zfproject.xml'

~/novo_projeto$ zf create controller Error 1 tecnico
~/projetoszend/novo_projeto$ zf create controller error 1 default
Creating a controller at ~/novo_projeto/application/modules/tecnico/controllers/ErrorController.php
Creating an index action method in controller Error
Creating a view script for the index action method at ~/novo_projeto/application/modules/tecnico/views/scripts/error/index.phtml
Updating project profile '~/novo_projeto/.zfproject.xml'

Isto criará dois arquivos:
/novo_projeto/application/modules/tecnico/controllers/GerenciaController.php; e
/novo_projeto/application/modules/tecnico/controllers/ErrorController.php
.

9. Criar os Actions

A lógica para criar um action é a seguinte:
zf create action NOME_DO_ACTION NOME_DO_CONTROLLER 1 NOME_DO_MODULE

O valor booleano ’1′ indica que queremos que o ZF Tool crie o arquivo ‘.phtml’. Ou seja, indica que se deseja que o Zend crie NÃO SOMENTE o método Action dentro do controller para cada ação que será criada (veja logo abaixo a descrição da mudança no arquivo IndexController.php) MAS TAMBÉM o arquivo correspondente View dentro do módulo correspondente para cada ação que será criada (veja abaixo a descrição da criação do arquivo quem-somos.phtml).

Primeiro, vamos criar o Action “error” para o controller Error:

~/novo_projeto$ zf create action error Error 1 tecnico
Creating an action named error inside controller at ~/novo_projeto/application/modules/tecnico/controllers/ErrorController.php
Updating project profile '~/novo_projeto/.zfproject.xml'
Creating a view script for the error action method at ~/novo_projeto/application/modules/tecnico/views/scripts/error/error.phtml
Updating project profile '~/novo_projeto/.zfproject.xml'

Como exemplo, vamos criar quatro páginas relativas a um mesmo tema, fazendo seu agrupamento em um único controlador (Gerencia) contendo as quatro ações.
Vamos usar o controlador “Gerencia” e as quatro ações serão:


    Page                Controller        Action
Home page                Gerencia         index
Adicionar novo álbum     Gerencia         add
Editar album             Gerencia         edit
Deletar album            Gerencia         delete

Os comandos para isto são:


zf create action add Gerencia 1 tecnico
zf create action edit Gerencia 1 tecnico
zf create action delete Gerencia 1 tecnico

Aqui transcrevemos a resposta do ZendFramework para o primeiro comando:

~/novo_projeto/$ zf create action add Gerencia 1 tecnico
Creating an action named add inside controller at ~/novo_projeto/application/modules/tecnico/controllers/GerenciaController.php
Updating project profile '~/novo_projeto/.zfproject.xml'
Creating a view script for the add action method at ~/novo_projeto/application/modules/tecnico/views/scripts/gerencia/add.phtml
Updating project profile '~/novo_projeto/.zfproject.xml'

Após o primeiro comando acima, dois fatos principais foram gerados:
a) o Zendframework adicionou o método correspondente ao Action “add” no arquivo “~/novo_projeto/application/modules/tecnico/controllers/GerenciaController.php“, ficando assim:

<?php
class Tecnico_GerenciaController extends Zend_Controller_Action
{
    (....)
    public function addAction()
    {
        // action body
    }
}

b) fora criado o arquivo “~/novo_projeto/application/modules/tecnico/views/scripts/gerencia/add.phtml“. Neste momento, já se pode acessar com o navegador a página http://novo_projeto.localhost/tecnico/gerencia/add que será mostrada uma página simples com a mensagem “View script for controller Gerencia and script/action name add”.

Para os outros comandos, o raciocínio é o mesmo. As páginas poderão ser acessadas em:
http://novo_projeto.localhost/tecnico/gerencia/edit
http://novo_projeto.localhost/tecnico/gerencia/delete

Observe como ficou a pasta “~/novo_projeto/application/modules/tecnico/views/scripts/gerencia/“:

-rw-r--r-- add.phtml
-rw-r--r-- edit.phtml
-rw-r--r-- delete.phtml
-rw-r--r-- index.phtml


Com os outros comandos executados, três novos métodos: addAction, editAction e deleteAction estarão criados em GerenciaController.php, bem como os scripts apropriados para o View (que serão necessários mais adiante). Tem-se agora todas as quarto ações necessárias.

O URL para cada ação é:


                        URL                                  Action method
http://novo_projeto.localhost/tecnico/gerencia/         GerenciaController::indexAction()
http://novo_projeto.localhost/tecnico/gerencia/add      GerenciaController::addAction()
http://novo_projeto.localhost/tecnico/gerencia/edit     GerenciaController::editAction()
http://novo_projeto.localhost/tecnico/gerencia/delete   GerenciaController::deleteAction()

10. Entendendo o roteamento usado pelo ZendFramework

Um conjunto de componenetes do ZendFramework (ZF) disponibilizam um sistema MVC completo para desenvolver aplicações que separam os templates da visão da lógica do negócio e dos arquivos de controle. São dois os componentes principais que implementam o MVC: Zend_Controller (o controlador) e o Zend_View (a visão). A família de classes do componente Zend_Controller oferece um padrão de design de Controlador Frontal (Front Controller design pattern) que despacha solicitações para as ações do controlador (actions) para que todo o processamento seja centralizado.

O componente Zend_Controller é o coração do sistema MVC do Zend Framework. É através deste componente que todos as chamadas web são interceptadas pelo controlador frontal e despachadas individualmente para ações baseadas no URL requerido. O processo do Zend_Controller é relativamente simples. Uma requisição é recebida pelo Zend_Controller_Front, que por sua vez chama Zend_Controller_Router_Rewrite para determinar qual controlador (e ação deste controlador) que será chamada. Zend_Controller_Router_Rewrite decompõe o URI para poder determinar os nomes do controlador e da ação da requisição. Zend_Controller_Front então entra em um laço de despacho. Ele chama Zend_Controller_Dispatcher_Standard, passando-lhe a requisição, para ser despachada para o controlador e ação especificados na requisição (ou usa os padrões “index”). Depois que o controlador termina, o controle retorna para Zend_Controller_Front. Se o controlador indicar outro controlador para ser despachado através do reinicio do status de requisição, o laço continua e outro despacho é executado. De outra maneira, o processo termina. Sobre detalhes do funcionamento do ZendController veja em “O Básico de Zend_Controller“.

Por tudo que mostramos neste post, vamos tentar entendender um pouco mais como as coisas estão funcionando. A estrutura de endereçamento utilizada pelo ZendFramework é a seguinte:
http://endereço-site/MODULE/CONTROLLER/ACTION

Ao fazer acesso à http://novo_projeto.localhost/tecnico/gerencia/produtos o módulo que se está utilizando chama-se “tecnico”, o controlador chama-se “gerencia” e a ação chama-se “produtos”.

Ao fazer acesso à http://novo_projeto.localhost/tecnico/gerencia/ o módulo que se está utilizando chama-se “tecnico”, o controlador chama-se “gerencia” e a ação chama-se “index” (que é o default do Zend). Observe que existe o arquivo ~/novo_projeto/application/modules/tecnico/views/scripts/gerencia/index.phtml que fora criado automaticamente pelo Zend, e no controlador “~/novo_projeto/application/modules/tecnico/controllers/GerenciaController.php” existe a função “public function indexAction()” também criada automaticamente pelo Zend.

Ou seja, por padrão, o primeiro seguimento de um caminho de um URL aponta para um módulo, o segundo para o controlador e o terceiro para uma ação. Por exemplo, dado o URL http://framework.zend.com/modulo1/roadmap/alugar, o caminho é /modulo1/roadmap/alugar, que irá apontar para o controlador “roadmap” e para a ação “alugar” no escopo do modulo1. Se nenhuma ação for informada, a ação “index” é assumida, e se nenhum controlador for informado, o controlador “index” é assumido (seguindo a convenção do Apache que mapeia um DirectoryIndex automaticamente).

O despachador do Zend_Controller toma o valor do controlador e mapeia-o para uma classe. Por padrão, ele pega o nome do controlador, com a primeira letra em maiúsculo, e acrescenta a palavra “Controller”. Sendo assim, em nosso exemplo acima, o controlador “roadmap” é mapeado para a classe RoadmapController. Semelhantemente, o valor da ação é mapeado para um método da classe do controlador. Por padrão, o valor é transformado em letras minúsculas, e a palavra “Action” é acrescentada. Sendo assim, em nosso exemplo acima, a ação “alugar” torna-se alugarAction(), e o método final chamado é RoadmapController::alugarAction().

Continua: veja a parte-2 deste material.

Referências:
1- Instalar e configurar o ZendFramework no Debian
2- ZendFramework: estruturar um novo projeto (parte 2)
3- Tutorial ZendFramework
4- Zend Programmer’s Reference Guide
5- ZendFramework: guia de referência do programador

Anúncios
comentários
  1. Altamiro disse:

    Ótima matéria, parabéns. A arquitetura do sistema está muito bem explicada. Parabéns

Deixe um comentário, pois isto é muito motivante para continuarmos este trabalho

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s