(Parte 1 de 4)

Sobre o Autor

Elton Luís Minetto possui graduação em Ciência de Computação pela Unochapecó e especialização em Ciência da Computação pela UFSC/UNOESC. Trabalha com PHP/MySQL desde 2000, com Linux desde 1997 e com MacOSX desde 2007. É autor do livro Frameworks para Desenvolvimento em PHP, da editora Novatec e co-autor do livro Grid Computing in Research and Education, publicado pela editora IBM/Redbooks, EUA.

Atualmente é sócio da Coderockr http://www.coderockr.com empresa de desenvolvimento de aplicativos para iOS e Web, trabalhando com consultoria, treinamento e desenvolvimento.

Pode ser encontrado no http://eminetto.me

Instalando o Zend Framework!6
Definindo o projeto! 7
Modelagem! 7
Estrutura do projeto! 9
Configurando o Apache! 9
Bootstrap! 10
Controladores! 13
Modelos! 14
Trabalhando com modelos e queries!17
Layout e visões! 20
Formulários! 23
Enviando arquivos! 26
Herança de formulários! 29
Subforms! 30
Criando um CRUD! 31
Desafio! 34
Organizando a aplicação! 34
Roteamento! 37
Autenticação! 38
Controle de acesso! 42
Cache! 52
Traduções! 57
Enviando e-mails! 59
Diagnóstico da aplicação! 63
Zend_log! 63
Zend_Db_Profiler! 65

Introdução

Como a idéia deste livro é ir direto ao ponto, vou fazer isso já na introdução.

A idéia desse livro não é explicar a teoria e filosofia do PHP, da orientação a objetos, as maravilhas dos design patterns, etc. Existem ótimos livros e sites que podem lhe ajudar a entender todos os conceitos envolvidos aqui. Entre os livros eu posso indicar:

• PHP Profissional. Alexandre Altair de Melo / Mauricio G. F.

Nascimento. Editora Novatec

• PHP Programando com Orientação a Objetos. Pablo

Dall’Oglio. Editora Novatec

• Zend Framework Componentes Poderosos para PHP. Flávio

Gomes da Silva Lisboa. Editora Novatec

• Zend Framework em Ação. Rob Allen, Nick Lo, Steven

Brown. Editora Alta Books.

Os três primeiros são escritos por autores brasileiros e são livros de grande importância e didática. O último é um clássico e também muito bom. O foco desde livro é ser um guia de desenvolvimento das principais funcionalidades do Zend Framework. Ele iniciou como uma apostila para cursos que venho ministrando nos últimos três ou quatro anos, então é algo que venho testando e alterando continuamente. Esta é a segunda edição deste e-book. Nesta edição procurei fazer uma atualização nos códigos e melhoria na explicação de alguns conceitos. Espero que lhe seja útil como tem sido para mim.

Instalando o Zend Framework

Instalar o Zend Framework é uma tarefa simples. O primeiro passo é verificar os seus requisitos básicos: um servidor web com suporte a reescrita de URLs (Apache será usado nestes exemplos) e o PHP 5.2.4 ou superior. No arquivo de configuração do Apache basta adicionar as linhas abaixo, ou alterá-las para refletir o seguinte:

LoadModule rewrite_module modules/mod_rewrite.so AddModule mod_rewrite.c AllowOverride all

Isto indica ao servidor que ele deve carregar o módulo que permite a reescrita de URLs (mais exemplos nos próximos tópicos) e permite o uso de configurações em arquivos especiais.

Agora basta fazer o download do framework, no site http://framework.zend.com

No momento da escrita deste livro a versão mais atual era a 1.1.1. No site é possível escolher entre três opções para download: a versão com o Zend Server, a versão Full e a versão Minimal do framework. A primeira é indicada se você quer a solução completa, com um servidor Apache e o MySQL já configurados. A versão full possui, além do framework, documentação, testes e demos. E a versão minimal é formada apenas pelo framework. Geralmente a versão minimal é a mais indicada. Depois de descompactar o arquivo é possível visualizar a seguinte estrutura (para a versão Minimal):

bin/ – scripts para a criação de projetos LICENSE.txt - uma cópia da licença usada pelo framework README.txt - instruções sobre instalação e documentação VERSION.txt – texto sobre a versão do framework library/ - neste diretório encontra-se o framework INSTALL.txt - instruções de instalação

O diretório library deve ser copiado para o diretório htdocs de seu servidor Apache. E pronto! O Zend Framework está pronto para uso.

Definindo o projeto

Na minha opinião a única forma de aprender uma nova ferramenta, linguagem, sistema operacional, é quando você realmente precisa resolver algum problema com ela. Pensando nisso, esse livro é baseado na construção de um aplicativo: um blog.

Mas um blog? Por alguns motivos:

• é um problema fácil de se entender. Todo mundo sabe como um blog funciona, seus requisitos e funcionalidades. Então a fase de requisitos do projeto é fácil de completar

• um blog apresenta um grande número de funcionalidades comuns a vários outros sites, como módulos, controle de acesso e permissões, upload de arquivos, tratamento de formulários, cache, traduções, integração com serviços externos, etc.

• a grande maioria dos frameworks possui um exemplo “como desenvolver um blog usando X”, então fica mais fácil para comparação se você já estudou algum outro framework como CakePHP, CodeIgniter ou mesmo Ruby on Rails

Modelagem

Agora que o convenci (ou não) de como desenvolver um blog pode lhe ajudar a entender o Zend Framework, vamos mostrar a modelagem das tabelas:

Simples, como deveria ser. Usando alguma ferramenta, como o PHPMyAdmin, SequelPro, ou o bom e velho terminal, é possível criar a estrutura do banco usando os comandos SQL abaixo:

CREATE DATABASE blog;

GRANT ALL privileges ON blog.* TO zend@localhost IDENTIFIED BY 'zend';

USE blog;

CREATE TABLE IF NOT EXISTS users ( id INT NOT NULL AUTO_INCREMENT ,

username VARCHAR(200) NOT NULL ,

password VARCHAR(250) NOT NULL ,

valid TINYINT NULL ,

PRIMARY KEY (id) ) ENGINE = InnoDB;

CREATE TABLE IF NOT EXISTS posts ( id INT NOT NULL AUTO_INCREMENT ,

title VARCHAR(250) NOT NULL ,

description TEXT NOT NULL ,

post_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ,

PRIMARY KEY (id) ) ENGINE = InnoDB;

CREATE TABLE IF NOT EXISTS comments ( id INT NOT NULL AUTO_INCREMENT ,

post_id INT NOT NULL ,

description TEXT NOT NULL ,

name VARCHAR(200) NOT NULL ,

email VARCHAR(250) NOT NULL ,

webpage VARCHAR(200) NOT NULL , comment_date TIMESTAMP NULL ,

PRIMARY KEY (id, post_id) ,

INDEX fk_comments_posts (post_id ASC) ,

CONSTRAINT `fk_comments_posts`

FOREIGN KEY (post_id )

REFERENCES posts (id )

ON UPDATE NO ACTION) ENGINE = InnoDB;

Estrutura do projeto

Vamos agora usar a ferramenta de geração de projetos do Zend Framework. No diretório bin do framework existem os arquivo zf.bat (Windows) e zf.sh (Linux/Mac OS X). É preciso que este arquivo e o executável do PHP estejam no caminho dos executáveis (PATH) do seu sistema operacional, ou executá-lo pelo caminho onde você salvou o framework. Para criar o projeto vamos executar:

./ZendFramework-1.1.1-minimal/bin/zf.sh create project blog

O diretório blog foi criado com o conteúdo:

Bootstrap.php - bootstrap da aplicação
configs - arquivos de configuração
controllers - controladores
models - modelos
views - visões

application - diretório da aplicação docs - documentações library - aqui devemos copiar o framework public - diretório de arquivos públicos tests - testes unitários

Configurando o Apache

Vamos também configurar um VirtualHost no Apache para facilitar os testes da aplicação. No arquivo httpd.conf (ou apache.conf) adicionar o seguinte (procure no arquivo docs/README.txt do projeto)

<VirtualHost *:80>

DocumentRoot "/caminho_htdocs/blog/public"
ServerName blog.local
# This should be omitted in the production environment
SetEnv APPLICATION_ENV development
<Directory "caminho_htdocs/blog/public">
Options Indexes MultiViews FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
</Directory>

</VirtualHost>

É necessário alterar os caminhos nas opções DocumentRoot e Directory para refletirem o caminho correto em sua máquina.

É preciso também alterar o arquivo hosts do sistema operacional para adicionar o endereço do blog.local. No Linux e Mac OS X, alterar o /etc/hosts e adicionar a linha:

No Windows o arquivo que deve ser alterado é o c:\windows \system32\drivers\etc\hosts e a linha a ser adicionada é igual a citada acima.

Bootstrap

No Zend Framework, existe um componente importante, chamado de Bootstrap que é responsável por receber todas as requisições, configurar o necessário (por exemplo: sessões, conexão com banco de dados, cache, etc) e invocar o controlador especificado pela URL que o usuário solicitou. Vou tentar explicar isso na forma de uma imagem:

O usuário faz uma requisição ao Apache, que invoca o Bootstrap (na imagem é o index.php). Este por sua vez faz a configuração necessária e passa a execução para o controlador. O controlador faz seu trabalho específico, podendo usar códigos contidos nos modelos e formatar visões que serão mostradas ao usuário. Ao final do processo do controlador, o Bootstrap volta a assumir e finaliza a requisição. Esta forma como o Zend Framework trabalha é muito interessante pois nos permite diversas flexibilidades e configurações. Se determinada configuração ou variável deve ser acessível a todos os pontos de nossa aplicação (controladores, modelos e visões) ela pode ser escrita no Bootstrap, pois sabemos que toda execução irá obrigatoriamente passar por ela. Outra vantagem é que se caso ocorra alguma exceção (Exceptions da linguagem PHP) que não for tratada por um controlador o Bootstrap irá recebê-la e podemos ter um ponto único no sistema para capturar e tratar erros. Todo este processo funciona da seguinte forma: o arquivo index.php cria uma instância da classe Zend_Application que usa a classe Bootstrap contida no Bootstrap.php. Ao ser inicializada, a aplicação irá executar todos os métodos cujo nome iniciem com _init. Podemos criar nosso Bootstrap inicial da seguinte forma:

<?php

* Salva o config no registry
* @return void
* @author Elton Minetto
*/

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap { /** public function _initConfig()

$config = new Zend_Config($this->getApplication()- >getOptions(), true); Zend_Registry::set('config', $config);

* Inicializa a sessão
*
* @return void
* @author Elton Minetto
*/

/** public function _initSession()

$session = new Zend_Session_Namespace('Blog');

Zend_Registry::set('session', $session);

* Inicializa o banco de dados. Somente necessário se desejado
*
* @return void
* @author Elton Minetto
*/

/** salvar a conexão no Registry public function _initDb()

Zend_Db_Table::setDefaultAdapter($db);

Zend_Registry::set('db', $db);

Nos próximos tópicos vamos adicionando ítens ao Bootstrap. Um novo conceito apresentado no código acima é o Zend_Registry. O registro é uma forma de armazenarmos objetos ou variáveis para que estes estejam acessíveis em toda a aplicação. É um mecanismo elegante para substituir o uso de variáveis globais e o Zend Framework faz uso extenso dele.

Controladores

Mas como o Bootstrap sabe qual é o controlador a ser executado? Isso é detectado pela URL que o usuário invocou. Funciona da seguinte forma:

http://BASE_URL/modulo/controlador/action/parametro/valor/

Exemplos:

http://blog.local/index/show/id/1 http://blog.local/admin/index/show/id/1

O primeiro link vai acessar o controlador IndexController dentro do módulo default (que é o módulo padrão, caso exista) e tentar invocar um método chamado showAction (a action) passando um parâmetro chamado id, com valor 1.

O segundo link vai acessar o controlador IndexController dentro do módulo admin (que é especificado na url) e tentar invocar um método chamado showAction (a action) passando um parâmetro chamado id, com valor 1.

Todos os controladores são classes que extendem uma classe chamada Zend_Controller_Action e devem estar em um arquivo cujo nome termine em Controller.php. Exemplo. Para criarmos os arquivos que atendam os exemplos acima, precisamos criar:

application/controllers/IndexController.php application/modules/admin/controllers/IndexController.php

O conteúdo do primeiro seria: <?php class IndexController extends Zend_Controller_Action {

public function showAction() {

e o conteúdo do segundo:

<?php class Admin_IndexController extends Zend_Controller_Action {

public function showAction() {

Note que o caminho do primeiro arquivo não está dentro de modules/default pois este é o módulo padrão, não sendo necessário criar desta forma caso estejamos usando apenas um módulo. Se estivermos usando mais de um módulo é recomendado criarmos o diretório, para ajudar na organização. Algumas observações sobre os códigos. A função showAction() deve ter o sufixo Action ou não será acessível ao usuário. Isto é uma forma de proteção do seu código. A classe Admin_IndexController indica que ela pertence ao módulo admin e é obrigatório ser definida desta forma. A classe IndexController não precisa indicar o nome do módulo pois o módulo default é o principal.

Modelos

Antes de iniciarmos a criação dos controladores e das visões precisamos criar a primeira camada da nossa aplicação MVC: os modelos. Para isso deve-se criar um arquivo para cada tabela e estes devem ser armazenados no diretório models. Todos os modelos são classes PHP que extendem a classe Zend_Db_Table_Abstract. O primeiro passo é configurarmos nosso projeto para acessar o banco de dados. Para isso vamos executar zf configure dbadapter "adapter=Pdo_Mysql&host=localhost&username=zend&password=zend&dbname= blog"

É preciso alterar os dados de username, password e nome do database, caso sejam diferentes Agora vamos criar o primeiro model, o arquivo models/Users.php

Users.php

<?php /** * Modelo da tabela users

*/ class Application_Model_Users extends Zend_Db_Table_Abstract { // nome da tabela no banco de dados protected $_name = 'users'; }

Posts.php <?php /** * Modelo da tabela posts

*/ class Application_Model_Posts extends Zend_Db_Table_Abstract { protected $_name = 'posts';

Comments.php <?php /** * Modelo da tabela comments

*/ class Application_Model_Comments extends Zend_Db_Table_Abstract { protected $_name = 'comments';

protected $_referenceMap = array(

'Post' => array (

'columns' => array('post_id'),

'refTableClass' => 'Posts',

'refColumns' => array('id')

Nos modelos Posts e Comments podemos ver o uso de um recurso interessante do Zend_Db_Table, os relacionamentos entre tabelas. Analisando a imagem da modelagem vemos que um post possui muitos comentários e que cada comentário pertence a um post (relacionamento um para muitos). No modelo Posts indicamos a relação das tabelas que dependem dela, usando o código:

E no modelo Comments os detalhes da tabela relacionada, com o código:

protected $_referenceMap = array( 'Post' => array (

'columns' => array('post_id'),

'refTableClass' => 'Posts',

'refColumns' => array('id')

Caso a tabela possua mais relacionamentos basta adicionar novos sub-arrays dentro do array $_referenceMap usando o mesmo modelo.

Com essa funcionalidade podemos facilmente, a partir de um blog recuperar seus comentários. Por exemplo, podemos usar um código similar ao abaixo, em um controlador, para recuperar os comentários (vamos ver mais exemplos sobre o uso dos models e dos controllers nos próximos tópicos)

Também é possível realizar o processo inverso. Digamos que eu precise buscar os dados do post relacionado a um determinado comentário:

O framework também fornece o suporte a relacionamentos “muitos para muitos”, que não faz parte do nosso exemplo, mas pode ser visto na documentação oficial (método findManyToManyRowset):

http://framework.zend.com/manual/en/zend.db.table.relationships.html

Trabalhando com modelos e queries

O Zend Framework fornece três formas de acessarmos os dados de uma base de dados: usando models, usando o Zend_Db_Select para gerar queries ou escrevendo a query sem o uso de objetos.

Exemplos usando Models Para recuperarmos todos os registros na tabela Posts:

Para recuperarmos apenas o registro com id = 1

Para fazermos insert de um registro

$posts = new Application_Model_Posts; $data = array ( 'title' => 'Título do post',

'description' => 'Texto do post' ); //insere e retorna o novo Id gerado pelo mysql $id = $posts->insert($data);

Para fazermos update de um registro

Para fazermos delete de um registro

Criando consultas SQL com Zend_Db_Select

O uso da classe Zend_Db_Select é muito simples, o intuito dela é proporcionar ao desenvolvedor a possibilidade de fazer consultas complexas sem a necessidade de escrever código SQL, e sim utilizando objetos. O construtor do Zend_Db_Select necessita uma conexão com um banco de dados. Podemos buscar a conexão com a base de dados que criamos no Bootstrap.php:

(Parte 1 de 4)

Comentários