Você está na página 1de 19

Iniciando com Zend Framework

Por Rob Allen, www.akrabat.com Traduo: Adler Brediks Medrado, http://www.neshertech.net/adler Reviso do documento 1.3.0 Copyright 2006, 2007 Este tutorial pretende dar uma introduo bsica ao uso do Zend Framework atravs de uma aplicao baseada em bancos de dados. NOTA: Este tutorial foi testado com as verses 0.9 e 0.9.1 do Zend Framework. Existe uma grande chance de ser compatvel com verses posteriores, mas certamente no funcionar com verses anteriores a 0.9. AVISO para a verso 0.9: Se voc fez o download da verso 0.9 do Zend Framework, ento voc precisar editar o arquivo library/Zend/Db/Table/Row/Abstract.php e adicionar < no incio da primeira linha.

Arquitetura Model-View-Controller (Modelo-Viso-Controle)


A maneira tradicional de desenvolver uma aplicao PHP fazer algo parecido com o seguinte:
<?php include "common-libs.php"; include "config.php"; mysql_connect($hostname, $username, $password); mysql_select_db($database); ?> <?php include "header.php"; ?> <h1>Home Page</h1> <?php $sql = "SELECT * FROM news"; $result = mysql_query($sql); ?> <table> <?php while ($row = mysql_fetch_assoc($result)) { ?> <tr> <td><?php echo $row['date_created']; ?></td> <td><?php echo $row['title']; ?></td> </tr> <?php } ?> </table> <?php include "footer.php"; ?>

Atravs do tempo de vida de uma aplicao, uma aplicao escrita desta forma se torna passvel de difcil manuteno conforme o cliente continue requisitando mudanas que so includas em diversos locais de seu cdigo. Um mtodo que melhora a manuteno de uma aplicao separar o cdigo de um arquivo em trs partes distintas (e normalmente arquivos separados): Model A parte de modelo de uma aplicao a parte que se preocupa com os dados especficos a serem mostrados. No cdigo de exemplo acima, o conceito de news. Dessa forma, model geralmente relacionado com a lgica de negcios de uma aplicao e administra o carregamento e o salvamento de dados em um banco de dados.

View Controller

A view consiste em uma pequena parte da aplicao que responsvel em mostrar a informao ao usurio. Normalmente, o HTML. O controller amarra o view e o model para garantir que as informaes corretas sejam mostradas na pgina.

O Zend Framework usa a arquitetura Model-View Controller (MVC). Isto usado para separar as diferentes partes de sua aplicao para tornar o desenvolvimento e manuteno mais fcil.

Requisitos
O Zend Framework possui os seguintes requisitos: PHP 5.1.4 (or maior) Um servidor web que suporte a funcionalidade de mod_rewrite (reescrita de URLs). Este tutorial assume que esteja sendo utilizado o Apache.

Obtendo o Framework
O Zend Framework pode ser baixado de http://framework.zend.com/download/stable nos formatos .zip ou .tar.gz. No momento em que o tutorial era escrito, a verso 0.9 era a verso corrente. Voc precisa baixar a verso 0.9 para este tutorial funcionar.

Estrutura de diretrios
Apesar de que o Zend Framework no designa uma estrutura de diretrio, o manual recomenda uma estrutura comum. Esta estrutura assume que voc tenha controle completo sobre a sua configurao do Apache, no entanto, ns queremos tornar a vida um pouco mais fcil, ento usaremos uma modificao. Comece criando um diretrio no diretrio raiz do servidor web chamado zf-tutorial. Isto significa que a URL que apontar para a aplicao ser: http://localhost/zf-tutorial. Crie os seguintes subdiretrios para receber os arquivos da aplicao:
zf-tutorial/ /application /controllers /models /views /filters /helpers /scripts /library /public /images /scripts /styles

Como voc pode ver, ns separamos diretrios para os arquivos de model, view e controller da sua aplicao. Imagens, scripts e arquivos CSS so guardados em diretrios separados sob o diretrio public. Os arquivos do Zend Framework sero colocados no diretrio library. Se ns precisarmos utilizar outras bibliotecas, elas podero ser colocadas l. Extraia o arquivo descarregado, no meu caso, ZendFramework-0.9.1-Beta.zip, para um diretrio temporrio. Todos os arquivos foram colocados em um subdiretrio chamado ZendFramework-0.9.1-Beta. Copie o contedo de ZendFramework-0.9.1Beta/library/Zend para zf-tutorial/library/. Seu diretrio zf-tutorial/library agora deve conter um sub-diretrio chamado Zend.

Inicializando
O controller do Zend Framework, Zend_Controller projetado para dar suporte a websites com

urls limpas. Para alcanar isso, todas as requisies precisam passar por um nico arquivo chamado index.php, conhecido como bootstraper. Isto nos prov um ponto central para todas as pginas da aplicao e garante que o ambiente est configurado corretamente para rodar a aplicao. Ns alcanamos isso usando um arquivo .htaccess no diretrio raiz zf-tutorial: zf-tutorial/.htaccess
RewriteEngine on RewriteRule .* index.php php_flag magic_quotes_gpc off php_flag register_globals off

A RewriteRule muito simples e pode ser interpretada como para qualquer url, redirecione para index.php. Ns tambm setamos um par de diretivas php para segurana e sanidade. Estes valores j deveriam estar setados corretamente no php.ini, mas ns queremos ter certeza disso. Note que a flag php_flag no .htaccess s funcionar se voc estiver usando mod_php. Se voc usa CGI/FastCGI, ento voc dever se certificar que o seu php.ini est correto. Porm, requisies para imagens, arquivos JavaScript e CSS no devero ser redirecionados para o nosso arquivo de inicializao. Mantendo estes arquivos dentro do subdiretrio pblico, ns podemos facilmente configurar o Apache para servir estes arquivos diretamente com outro arquivo .htaccess em zf-tutorial/public: zf-tutorial/public/.htaccess
RewriteEngine off

Apesar de no ser estritamente necessrio, ns podemos adicionar mais um par de arquivos .htaccess para garantir que nossos diretrios application and library estejam protegidos: zf-tutorial/application/.htaccess
deny from all

zf-tutorial/library/.htaccess
deny from all

Note que para que os arquivos .htaccess sejam usados pelo Apache Note that for .htaccess , a diretiva de configurao AllowOverride precisa estar setada como All no seu arquivo httpd.conf. A idia aqui apresentada de usar mltiplos arquivos .htaccess do artigo Blueprint for PHP Applications: Bootstrapping (Parte 2) de Jayson Minard. Eu recomendo a leitura das duas partes.

O arquivo de inicializao: index.php


O arquivo zf-tutorial/index.php o nosso arquivo de bootstrap e ns o iniciaremos com o cdigo a seguir: zf-tutorial/index.php
<?php error_reporting(E_ALL|E_STRICT); date_default_timezone_set('Europe/London'); set_include_path('.' . PATH_SEPARATOR . './library' . PATH_SEPARATOR . './application/models/' . PATH_SEPARATOR . get_include_path()); include "Zend/Loader.php"; Zend_Loader::loadClass('Zend_Controller_Front'); // setup controller $frontController = Zend_Controller_Front::getInstance(); $frontController->throwExceptions(true); $frontController->setControllerDirectory('./application/controllers');

// run! $frontController->dispatch();

Repare que ns no colocamos a tag ?> no final do arquivo porque isso no necessrio e deixar isso for a ir prevenir alguns erros difceis de debugar quando utilizar o redirecionamento via funo header() caso exista algum espao em branco aps a tag ?>. Vamos percorrer o arquivo.
error_reporting(E_ALL|E_STRICT); date_default_timezone_set('Europe/London');

Estas linhas iro nos garantir que ns veremos qualquer erro que gerarmos (assumindo que a diretiva display_errors esteja como on). Ns tambm selecionamos nosso fuso-horrio corrente conforme requerido pelo PHP 5.1+. Obviamente voc deve escolher o seu fusohorrio.
set_include_path('.' . PATH_SEPARATOR . './library' . PATH_SEPARATOR . './application/models/' . PATH_SEPARATOR . get_include_path()); include "Zend/Loader.php";

O Zend Framework projetado para que seus arquivos estejam no include_path. Ns tambm colocamos nosso diretrio de modelos (models) no include_path para que ns possamos carreg-los facilmente depois. Para iniciar, ns precisamos incluir o arquivo Zend/Loader.php que nos dar acesso classe Zend_Loader que possui as funes estticas que nos permitir carregar qualquer outra classe do Zend Framework.
Zend_Loader::loadClass('Zend_Controller_Front'); Zend_Loader::loadClass carrega a classe desejada. Isto feito pela converso dos

underscores do nome da classe em separadores de diretrio e adicionando .php no final. Dessa forma, a classe Zend_Controller_Front ser carregada do arquivo Zend/Controller/Front.php. Se voc seguir a mesma conveno para as suas prprias bibliotecas de classes, ento voc poder utilizar Zend_Loader::loadClass() para carreg-las tambm. A primeira classe que ns precisamos a front controller. A front controller utilizar uma classe de roteamento que mapeia a URL requisitada para a funo correta que ser utilizada para mostrar a pgina. Para que o roteador seja operado, ele precisa tirar qual parted a URL o caminho para o nosso index.php e ento ele poder procurar pelos elementos da URI. Isto feito pelo objeto Request. Ele faz um bom trabalho de auto-deteco da URL base correta, mas caso no funcione para a sua configurao, ento voc pode sobrescrev-lo usando a funo $frontController->setBaseUrl(). Ns precisaremos configurar o front controller para que ele saiba em qual diretrio se encontra os nossos controllers.
$frontController = Zend_Controller_Front::getInstance(); $frontController->setControllerDirectory('./application/controllers'); $frontController->throwExceptions(true);

Como isto um tutorial e ns estamos executando um sistema de testes, eu decide instruir o front controller para disparar todas as excees que ocorrerem. Por padro, o front controller ir captur-los para ns e armazen-los na propriedade _exceptions do objeto Response que ele cria. O objeto response guarda toda a informao sobre a resposta para a URL requisitada. Isto inclui os cabealhos http, o contedo da pgina e as excees. O front controller ir enviar os cabealhos e mostrar o contedo da pgina antes de ele completar o trabalho. Isto pode ser um pouco confuso para as pessoas que so novatas com o Zend Framework,

ento mais fcil apenas re-jogar as excees. claro que em um servidor de produo voc no dever mostrar os erros ao usurio de forma nenhuma. Finalmente, ns chegamos no ponto principal e vamos rodar nossa aplicao:
// run! $frontController->dispatch();

Se voc digitar http://localhost/zf_tutorial/ para testar, voc certamente encontrar um erro similar a: Fatal error: Uncaught exception 'Zend_Controller_Dispatcher_Exception' with message 'Invalid controller specified (index)' in Isto est nos dizendo que ns no configuramos nossa aplicao ainda. Antes de fazermos isso, ns iremos discutir o que ns iremos construir, ento vamos fazer isso a seguir.

O Website
Ns iremos construir um sistema muitos simples estoque para mostrar a nossa coleo de CD. A pgina principal ir listar a nossa coleo and nos permitir adicionar, editar e excluir CDs. Ns iremos gravar nossa lista em um banco de dados em um esquema como este: Campo Id Artist Title Tipo Integer Varchar(100) Varchar(100) Null? No No No Descrio Primary key, Autoincrement

Pginas necessrias
As pginas a seguir sero necessrias Home page Ir mostrar a lista dos lbuns e providenciar links para edit-los e deleta-los. Um link que permitir adicionar novos lbuns tambm estar disponvel. Adicionar New Album Mostrar um formulrio para adicionar um novo lbum Edit Album Mostrar um formulrio para edio de um lbum Delete Album Esta pgina ir confirmar que ns queremos deletar um lbum e ento o deletar.

Organizando as pginas
Antes de ns configurarmos nossos arquivos, importante entender como o framework espera que as pginas sejam organizadas. Cada pgina da aplicao conhecida como uma ao e aes so agrupadas em controllers. Ex: para a URL com o formato http://localhost/zf-tutorial/news/view, o controller news e a ao view. Isto permite um agrupamento de aes relacionadas. Por exemplo, o controller news pode ter aes atual, arquivadas e ler. O sistema de MVC do Zend Framework tambm suporta mdulos para agrupar controllers, mas esta aplicao no grande o suficiente para nos preocuparmos com isso. O Controller do Zend Framework reserve uma ao especial chamada index como uma ao padro. Isto , uma url como http://localhost/zf-tutorial/news/ executar uma ao index que est no controller news. O Controller do Zend Framework tambm reserve um controller padro para caso nenhuma seja solicitado. No nenhuma surpresa se ele se chamar index tambm. Dessa forma, a url http://localhost/zf-tutorial/ ir fazer com que a ao index no controller index seja executada. Como este um simples tutorial, ns no iremos nos incomodar com coisas complicadas como login.

Isso pode esperar por um tutorial separado... Como ns temos quarto pginas que se aplicam a lbuns, ns iremos agrup-las em um nico controller como quatro aes. Ns devemos usar o controller default e as quatro aes sero: Pgina Pgina principal Adicionar novo lbum Editar lbum Excluir Album Bom e simples. Controller Index Index Index Index Ao Index Add Edit Delete

Configurando o Controle
Agora ns estamos prontos para configurar o nosso controller. No Zend Framework, o controller uma classe que precisa ser denominada {Nome}Controller. Veja que {Nome} precisa comear com uma letra maiscula. Esta classe precisa estar em um arquivo chamado {Nome}Controller.php dentro do diretrio de controllers especificado. Novamente, {Nome} precisa iniciar com uma letra maiscula e todas as outras precisam ser minsculas. Cada ao um mtodo pblico dentro da classe de controle e precisa se chamar {ao}Action. Neste caso, {ao} deve iniciar como uma letra minscula. Assim, nossa classe de controle denominada IndexController que est definida em zf-tutorial/application/controllers/IndexController.php: zf-tutorial/application/controllers/IndexController.php
<?php class IndexController extends Zend_Controller_Action { function indexAction() { echo "<p>em IndexController::indexAction()</p>"; } function addAction() { echo "<p>em IndexController::addAction()</p>"; } function editAction() { echo "<p>em IndexController::editAction()</p>"; } function deleteAction() { echo "<p>em IndexController::deleteAction()</p>"; } }

Inicialmente, ns definimos que cada ao imprima seu prprio nome. Teste isso navegando pelas URLs: URL http://localhost/zf_tutorial/ http://localhost/zf_tutorial/index/add http://localhost/zf_tutorial/index/edit http://localhost/zf_tutorial/index/delete Texto apresentado em IndexController::indexAction() em IndexController::addAction() em IndexController::editAction() em IndexController::deleteAction()

Ns temos agora um roteador funcionando e as aes esto sendo executadas corretamente

para cada pgina de nossa aplicao. Caso isso no funcione com voc, confira na seo Defeitos que se encontra no final deste tutorial e veja se te ajuda. hora de construirmos a view.

Configurando a Viso
O Componente de viso do Zend Framework chamado, de certa forma sem surpreender, Zend_View. O componente de viso nos permitir separar o cdigo que mostra a pgina do cdigo dos mtodos de ao. O uso bsico do Zend_View :
$view = new Zend_View(); $view->setScriptPath('/caminho/para/arquivos_de_visao'); echo $view->render('view.php');

Podemos observar facilmente que se ns colocarmos este esqueleto diretamente em cada um de nossos mtodos de ao, ns iremos repetir o cdigo de configurao, o que no interessa da ao. Ns devemos de preferncia, fazer a inicializao da viso em algum local e ento acessar o nosso objeto que j est inicializado, em cada um dos mtodos de ao. Os projetistas do Zend Framework previram este tipo de problema e a soluo foi criar o Zend_Controller_Action para ns. L tem dois mtodos auxiliares: initView() e render(). O mtodo initView() cria um objeto Zend_View para ns e determina-o para a propriedade $view, deixando pronto para que sejam atribudos dados a ele. Ele tambm configure o objeto Zend_View para procurar em views/scripts/{controller} pelos scripts de viso que devem ser renderizados. O processo de renderizao de um script de viso feito pelo render(), que vai (por padro, ao menos) renderizar o script {ao}.phtml e anexar isso ao corpo do objeto Response. O Objeto Response pe usado para combinar todos os cabealhos, contedo de corpo e excees geradas como resultado do uso do sistema de MVC. O front controller ento automaticamente envia os cabealhos e em seguida o corpo do contedo no final. Para integrar a viso na nossa aplicao ns precisamos inicializar a viso no mtodo init() e ento assegurar que chamaremos o mtodo render() em cada ao. Ns precisamos tambm criar alguns arquivos de viso com cdigo para testes de exibio. A seguir, as mudanas necessrias no IndexController (mudanas em negrito). Como voc pode ver, ns adicionamos um novo mtodo chamado init(), que automaticamente executado pelo construtor do Zend_Controller_Action para ns. Isto nos garante que a viso foi inicializada no incio e ns podemos ter confiana que ela est pronta para uso nos mtodos de ao.

zf-tutorial/application/controllers/IndexController.php
<?php class IndexController extends Zend_Controller_Action { function init() { $this->initView(); } function indexAction() { $this->view->title = "Meus lbuns"; $this->render(); } function addAction() { $this->view->title = "Adicionar novo lbum"; $this->render(); } function editAction() { $this->view->title = "Editar lbum"; $this->render(); } function deleteAction() { $this->view->title = "Delete Album"; $this->render(); } }

Em cada mtodo, ns determinamos uma varivel chamada title propriedade view e ento chamamos render() para mostrar a template view. Repare que a exposio no ocorre neste ponto - Isto feito pelo front controller no final do processo. Agora ns precisamos adicionar quarto arquivos de viso para a nossa aplicao. Estes arquivos so conhecidos como templates e o mtodo render() espera que cada arquivo de template tenha a extenso .phtml para demonstrar que este um arquivo de template. O arquivo precisa estar em um subdiretrio que foi criado aps o controller, ento os quatro arquivos so: zf-tutorial/application/views/scripts/index/index.phtml
<html> <head> <title><?php echo $this->escape($this->title); ?></title> </head> <body> <h1><?php echo $this->escape($this->title); ?></h1> </body> </html>

zf-tutorial/application/views/scripts/index/add.phtml
<html> <head> <title><?php echo $this->escape($this->title); ?></title> </head> <body> <h1><?php echo $this->escape($this->title); ?></h1> </body> </html>

zf-tutorial/application/views/scripts/index/edit.phtml
<html> <head> <title><?php echo $this->escape($this->title); ?></title> </head> <body> <h1><?php echo $this->escape($this->title); ?></h1> </body> </html>

zf-tutorial/application/views/scripts/index/delete.phtml
<html> <head> <title><?php echo $this->escape($this->title); ?></title> </head> <body> <h1><?php echo $this->escape($this->title); ?></h1> </body> </html>

O teste para cada controle/ao dever mostrar os quatro ttulos em negrito.

Cdigos HTML comum


Rapidamente notamos que existem muito cdigo HTML comum em nossas views. Ns iremos colocar o cdigo html que obvio em dois arquivos: header.phtml e footer.phtml dentro do diretrio scripts. Ns poderemos ento utiliz-los para armazenar o cdigo HTML comum e somente fazer uma referncia a eles da template de viso. Os novos arquivos so: zf-tutorial/application/views/scripts/header.phtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> <title><?php echo $this->escape($this->title); ?></title> </head> <body> <div id="content">

(Repare que ns corrigimos o HTML, ento ns estamos compatveis com o padro tambm!) zf-tutorial/application/views/scripts/footer.phtml
</div> </body> </html>

Novamente, nossas vises precisam de mudanas: zf-tutorial/application/views/scripts/index/index.phtml


<?php echo $this->render('header.phtml'); ?> <h1><?php echo $this->escape($this->title); ?></h1> <?php echo $this->render('footer.phtml'); ?>

zf-tutorial/application/views/scripts/index/add.phtml
<?php echo $this->render('header.phtml'); ?> <h1><?php echo $this->escape($this->title); ?></h1> <?php echo $this->render('footer.phtml'); ?>

zf-tutorial/application/views/scripts/index/edit.phtml
<?php echo $this->render('header.phtml'); ?> <h1><?php echo $this->escape($this->title); ?></h1> <?php echo $this->render('footer.phtml'); ?>

zf-tutorial/application/views/scripts/index/delete.phtml
<?php echo $this->render('header.phtml'); ?> <h1><?php echo $this->escape($this->title); ?></h1> <?php echo $this->render('footer.phtml'); ?>

Estilos
Mesmo que isso somente um tutorial, ns precisaremos de um arquivo CSS para tornar a nossa aplicao um pouco apresentvel! Isso causa um pequeno problema porque atualmente ns no sabemos como referenciar o arquivo CSS porque a URL no aponta para o diretrio raiz correto. Para resolver isso, ns usamos o mtodo getBaseURL() que parte da requisio (request) e passamos isso para a viso (view). Isto provm para ns a pequena parte da URL que ns desconhecemos. Altere o IndexController::init() para que se parea com isso: zf-tutorial/application/controllers/IndexController.php
... function init() { $this->initView(); $this->view->baseUrl = $this->_request->getBaseUrl(); } ...

Ns precisamos adicionar o arquivo CSS para a seo <head> do arquivo header.phtml: zf-tutorial/application/views/scripts/header.phtml
... <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> <title><?php echo $this->escape($this->title); ?></title> <link rel="stylesheet" type="text/css" media="screen" href="<?php echo $this->baseUrl;?>/public/styles/site.css" /> </head> ...

Finalmente, ns precisamos de alguns estilos CSS: zf-tutorial/public/styles/site.css


body,html { font-size:100%; margin: 0; font-family: Verdana,Arial,Helvetica,sans-serif; color: #000; background-color: #fff; } h1 { font-size:1.4em; color: #800000; background-color: transparent; } #content { width: 770px; margin: 0 auto; } label { width: 100px; display: block; float: left; }

#formbutton { margin-left: 100px; } a { color: #800000; }

Isto deve tornar ligeiramente mais bonito!

O Banco de dados
Agora que temos o controle da aplicao separado da viso, hora de olhar a seo de modelo da nossa aplicao. Lembre-se que o modelo a parte que lida com o ncleo da aplicao (tambm chamado de regras de negcio) , no nosso caso, lida com o banco de dados. Ns faremos uso da classe Zend_Db_Table do Zend Framework que usada para pesquisar, inserir, alterar e excluir linhas de uma tabela do banco de dados.

Configurao
Para usar a Zend_Db_Table,ns precisamos dizer a ela qual o banco de dados que usaremos e tambm o usurio e a senha. Como ns preferimos no colocar estes dados dentro da nossa aplicao, ns usaremos um arquivo de configurao para guardar esta informao. O Zend Framework oferece a classe Zend_Config para oferecer um acesso orientado a objetos a arquivos de configurao. O arquivo de configurao pode ser um arquivo INI ou um arquivo XML. Ns usaremos o arquivo INI: zf-tutorial/application/config.ini
[general] db.adapter = PDO_MYSQL db.config.host = localhost db.config.username = rob db.config.password = 123456 db.config.dbname = zftest

Obviamente voc deve usar o seu nome de usurio, senha e banco de dados, no o meu! muito fcil usar o Zend_Config:
$config = new Zend_Config_Ini('config.ini', 'section');

Repare que neste caso, Zend_Config_Ini carrega uma seo do arquivo INI e no todas as sees do arquivo (mas todas as sees podem ser carregadas se voc desejar). Ele suporta uma notao no nome da seo para permitir que sejam carregadas sees adicionais. Zend_Config_Ini tambm trata o ponto no parmetro como separadores hierrquicos que permite o agrupamento de parmetros de configurao relacionados. No nosso config.ini, os parmetros servidor (host), usurio (username) e o nome do banco de dados (dbname) sero agrupados em $config->db->config. Ns iremos carregar o nosso arquivo de configurao no nosso arquivo de inicializao (index.php):

Parte relevante de zf-tutorial/index.php


... Zend_Loader::loadClass('Zend_Controller_Front'); Zend_Loader::loadClass('Zend_Config_Ini'); Zend_Loader::loadClass('Zend_Registry'); // load configuration $config = new Zend_Config_Ini('./application/config.ini', 'general'); $registry = Zend_Registry::getInstance(); $registry->set('config', $config); // setup controller ...

As mudanas esto em negrito. Ns carregamos as classes que vamos utilizar (Zend_Config_Ini and Zend_Registry) e ento carregar a sesso general de application/config.ini em nosso objeto $config. Finalmente ns atribuimos o objeto $config ao registro para que possamos recuper-lo em qualquer lugar da aplicao. Nota: Neste tutorial, ns no precisamos guardar o $config no registro, mas uma boa prtica em uma aplicao real que voc ter mais que uma configurao de banco de dados no arquivo INI. Porm, esteja avisado que o registro um pouco global e causa dependncias entre objetos que no deveriam depender um do outro, se voc no for cuidadoso.

Configurando Zend_Db_Table
Para usar a Zend_Db_Table, ns precisaremos informar a configurao de banco de dedos que ns carregamos. Para fazer isso ns precisamos criar uma instncia da Zend_Db e ento registra-la usando o mtodo esttico Zend_Db_Table:: setDefaultAdapter(). Novamente, ns fazemos isso no arquivo de inicializao (adies em negrito): Parte relevante de zf-tutorial/index.php
... Zend_Loader::loadClass('Zend_Controller_Front'); Zend_Loader::loadClass('Zend_Config_Ini'); Zend_Loader::loadClass('Zend_Registry'); Zend_Loader::loadClass('Zend_Db'); Zend_Loader::loadClass('Zend_Db_Table'); // load configuration $config = new Zend_Config_Ini('./application/config.ini', 'general'); $registry = Zend_Registry::getInstance(); $registry->set('config', $config); // setup database $db = Zend_Db::factory($config->db->adapter, $config->db->config->asArray()); Zend_Db_Table::setDefaultAdapter($db); // setup controller ...

Criando a tabela
Eu estarei usando MySQL e ento o comando SQL para criar a tabela :
CREATE TABLE album ( id int(11) NOT NULL auto_increment, artist varchar(100) NOT NULL, title varchar(100) NOT NULL, PRIMARY KEY (id) )

Execute o comando em um client MySQL como o phpMyAdmin ou o cliente de linha de comando padro.

Inserindo albums de teste


Ns precisaremos inserir algumas linhas na tabela para que ns possamos testar a funcionalidade de recuperao da pgina principal. Eu estarei pegando os primeiros dois CDs Hot 100 do site Amazon.co.uk:
INSERT INTO album (artist, title) VALUES ('James Morrison', 'Undiscovered'), ('Snow Patrol', 'Eyes Open');

O Modelo
Zend_Db_Table uma classe abstrata, ento ns temos que derivar nossa classe que especfica para gerenciar os albums. No importa como denominaremos a nossa classe, mas faz sentido que ela tenha o mesmo nome que a tabela do banco de dados. Assim, nossa classe ser denominada lbum como a nossa tabela que se chama lbum. Para informar a Zend_Db_Table o nome da tabela que iremos gerenciar, ns temos que setar a propriedade protegida $_name para o mesmo nome da tabela. Tambm, Zend_Db_Table assume que a chave primria da sua tabela seja denominada id que auto-incrementada pelo banco de dados. O nome deste campo pode ser mudado tambm se necessrio. Ns iremos guardar nossa classe lbum no diretrio models: zf-tutorial/application/models/Album.php
<?php class Album extends Zend_Db_Table { protected $_name = 'album'; }

No muito complicado, n?! Felizmente para ns, nossas necessidades so muito simples e a Zend_Db_Table fornece toda a funcionalidade que precisamos. De qualquer forma, se voc necessita de alguma funcionalidade especfica para gerenciar seu modelo, ento nesta classe que voc deve coloc-la. Geralmente, as funcionalidades adicionais que sero mtodos como find que retornaro colees de dados que voc precisa. Voc tambm pode informar a Zend_Db_Table sobre relacionamentos de tabelas e ela busca os dados relacionados tambm.

Listando os albums
Agora que ns j fizemos a configurao, ns podemos ir para a parte a aplicao que mostra alguns lbuns. Isto sera feito na classe IndexController. Claramente, toda ao em IndexController ser manipulando o banco de dados lbum usando a classe lbum, ento faz sentido que a classe lbum seja carregada quando o controller seja instanciado. Isso pode ser feito pelo mtodo init(): zf-tutorial/application/controllers /IndexController.php
... function init() { $this->initView(); $this->view->baseUrl = $this->_request->getBaseUrl(); Zend_Loader::loadClass('Album'); } ...

Nota: Este um exemplo de como usar Zend_Loader::loadClass() para carregar nossas prprias classes e funciona porque ns colocamos o diretrio models no include path em index.php.

Ns iremos listar os lbuns em uma tabela com indexAction(): zf-tutorial/application/controllers/IndexController.php


... function indexAction() { $this->view->title = "My Albums"; $album = new Album(); $this->view->albums = $album->fetchAll(); $this->render(); } ...

O mtodo Zend_Db_Table::fetchAll() retorna uma Zend_Db_Table_Rowset que nos permitir iterar pelas linhas retornadas no arquivo de template da view: zf-tutorial/application/views/scripts/index/index.phtml
<?php echo $this->render('header.phtml'); ?> <h1><?php echo $this->escape($this->title); ?></h1> <p><a href="<?php echo $this->baseUrl; ?>/index/add">Adicionar novo album</a></p> <table> <tr> <th>Titulo</th> <th>Artista</th> <th>&nbsp;</th> </tr> <?php foreach($this->albums as $album) : ?> <tr> <td><?php echo $this->escape($album->title);?></td> <td><?php echo $this->escape($album->artist);?></td> <td> <a href="<?php echo $this->baseUrl; ?>/index/edit/id/<?php echo $album->id;?>">Edit</a> <a href="<?php echo $this->baseUrl; ?>/index/delete/id/<?php echo $album->id;?>">Delete</a> </td> </tr> <?php endforeach; ?> </table> <?php echo $this->render('footer.phtml'); ?>

http://localhost/zf-tutorial/ (or de onde voc estiver chamando!) dever mostrar agora uma bela lista de (dois) lbuns.

Adicionando novos lbuns


Ns poderemos agora codificar a funcionalidade para adicionar novos lbums. Abaixo duas partes: Mostrar um formulrio para o usurio fornecer os detalhes Processar a submisso do formulrio e gravar em um banco de dados Isso feito com addAction(): zf-tutorial/application/controllers/IndexController.php
... function addAction() { $this->view->title = "Adicionar novo lbum"; if (strtolower($_SERVER['REQUEST_METHOD']) == 'post') { Zend_Loader::loadClass('Zend_Filter_StripTags');

$filter = new Zend_Filter_StripTags(); $artist = $filter->filter($this->_request->getPost('artist')); $artist = trim($artist); $title = trim($filter->filter($this->_request->getPost('title'))); if ($artist != '' && $title != '') { $data = array( 'artist' => $artist, 'title' => $title, ); $album = new Album(); $album->insert($data); $this->_redirect('/'); return; } } // set up an "empty" album $this->view->album = new stdClass(); $this->view->album->id = null; $this->view->album->artist = ''; $this->view->album->title = ''; // additional view fields required by form $this->view->action = 'add'; $this->view->buttonText = 'Add'; $this->render(); } ...

Observe como ns checamos a varivel $_SERVER['REQUEST_METHOD'] para ver se o formulrio foi submetido.. Se ele foi, ns recuperamos o artista e o titulo do array post e usamos a classe Zend_Filter_StripTags para garantir que nenhum html seja permitido. Ento, assumindo que eles foram informados, ns utilizamos nossa classe de modelo, lbum(), para inserir a informao em uma nova linha na tabela do banco de dados. Depois que ns adicionamos o lbum, ns redirecionamos usando o mtodo _redirect() do controle para voltarmos raiz da nossa aplicao. Finalmente, ns deixamos a view pronta para o formulrio que vamos usar na template. Ns podemos ver que a ao edit do formulrio ser bastante similar com esta, ento ns usaremos um arquivo de template comum (_form.phtml) que chamado de indexAdd.tpl.php e indexEdit.tpl.php: As templates para adicionar lbum so: zf-tutorial/application/views/scripts/index/add.phtml
<?php echo $this->render('header.phtml'); ?> <h1><?php echo $this->escape($this->title); ?></h1> <?php echo $this->render('index/_form.phtml'); ?> <?php echo $this->render('footer.phtml'); ?>

zf-tutorial/application/views/scripts/index/_form.phtml
<form action="<?php echo $this->baseUrl ?>/index/<?php echo $this->action; ?>" method="post"> <div> <label for="artist">Artist</label> <input type="text" name="artist" value="<?php echo $this->escape(trim($this->album->artist));?>"/> </div> <div> <label for="title">Title</label>

<input type="text" name="title" value="<?php echo $this->escape($this->album->title);?>"/> </div> <div id="formbutton"> <input type="hidden" name="id" value="<?php echo $this->album->id; ?>" /> <input type="submit" name="add" value="<?php echo $this->escape($this->buttonText); ?>" /> </div> </form>

Estes so cdigos razoavelmente simples. Como ns intencionamos usar _form.phtml para a ao edit, ns usamos uma varivel $this->action. Similarmente, ns usamos uma varivel para o texto que ser mostrado no boto de envio.

Editando um lbum
Editar um lbum quase idntico a adicionar um, ento o cdigo muito similar: zf-tutorial/application/controllers/IndexController.php
... function editAction() { $this->view->title = "Editar lbum"; $album = new Album(); if (strtolower($_SERVER['REQUEST_METHOD']) == 'post') { Zend_Loader::loadClass('Zend_Filter_StripTags'); $filter = new Zend_Filter_StripTags(); $id = (int)$this->_request->getPost('id'); $artist = $filter->filter($this->_request->getPost('artist')); $artist = trim($artist); $title = trim($filter->filter($this->_request->getPost('title'))); if ($id !== false) { if ($artist != '' && $title != '') { $data = array( 'artist' => $artist, 'title' => $title, ); $where = 'id = ' . $id; $album->update($data, $where); $this->_redirect('/'); return; } else { $this->view->album = $album->fetchRow('id='.$id); } } } else { // album id should be $params['id'] $id = (int)$this->_request->getParam('id', 0); if ($id > 0) { $this->view->album = $album->fetchRow('id='.$id); } } // additional view fields required by form $this->view->action = 'edit'; $this->view->buttonText = 'Update'; $this->render(); } ...

Note que quando no estamos em modo post, ns recuperamos o parmetro id da propriedade params usando getParam().

O Template : zf-tutorial/application/views/scripts/index/edit.phtml
<?php echo $this->render('header.phtml'); ?> <h1><?php echo $this->escape($this->title); ?></h1> <?php echo $this->render('index/_form.phtml'); ?> <?php echo $this->render('footer.phtml'); ?>

Mudana!
Voc no deve ter deixado de perceber que os mtodos AddAction() e EditAction() so muito similares e que as templates add e edit so idnticas. Alguma mudana necessria! Eu deixarei isso como um exerccio para voc, prezado leitor...

Excluindo um lbum
Para arredondar a nossa aplicao, ns precisamos adicionar a excluso. Ns temo um link Delete perto de cada lbum em nossa pgina de listagem e ele tem que executar uma excluso quando ele clicado passando os parmetros por GET. Isto pode estar errado. Relembrando nossa especificao HTTP, ns no devemos fazer uma ao irreversvel usando GET e devemos usar POST. O recente accelerator beta do Google trouxe este ponto a tona para muitas pessoas. Ns mostraremos um formulrio de confirmao quando o usurio clicar em excluir e se ele clicar em sim, ns faremos a excluso. O cdigo parece um pouco familiar com as aes de adicionar e editar: zf-tutorial/application/controllers/IndexController.php
... function deleteAction() { $this->view->title = "Excluir Album"; $album = new Album(); if (strtolower($_SERVER['REQUEST_METHOD']) == 'post') { Zend_Loader::loadClass('Zend_Filter_Alpha'); $filter = new Zend_Filter_Alpha(); $id = (int)$this->_request->getPost('id'); $del = $filter->filter($this->_request->getPost('del')); if ($del == 'Yes' && $id > 0) { $where = 'id = ' . $id; $rows_affected = $album->delete($where); } } else { $id = (int)$this->_request->getParam('id'); if ($id > 0) { $this->view->album = $album->fetchRow('id='.$id); if ($this->view->album->id > 0) { $this->render(); return; } } } // redireciona listagem novamente $this->_redirect('/'); } ...

Novamente, ns usamos o mesmo truque de checar o mtodo de requisio para verificar se iremos mostrar o formulrio de confirmao ou se ns devemos realizar a excluso, via classe lbum(). Como insert e update, a atual excluso feita via uma chamada a Zend_Db_Table::delete(). Observe que ns retornamos imediatamente aps setar o response. Isto porque ns podemos redirecionar de voltar para a listagem de lbuns no final do mtodo. Assim, se alguma das checagens falharem, ns voltamos listagem de lbuns sem precisar chamar _redirect() diversas vezes dentro do mtodo. O Template um simples formulrio: zf-tutorial/application/views/indexDelete.tpl.php
<?php echo $this->render('header.phtml'); ?> <h1><?php echo $this->escape($this->title); ?></h1> <?php if ($this->album) :?> <form action="<?php echo $this->baseUrl ?>/index/delete" method="post"> <p>Are you sure that you want to delete '<?php echo $this->escape($this->album->title); ?>' by '<?php echo $this->escape($this->album->artist); ?>'? </p> <div> <input type="hidden" name="id" value="<?php echo $this->album->id; ?>" /> <input type="submit" name="del" value="Yes" /> <input type="submit" name="del" value="No" /> </div> </form> <?php else: ?> <p>Cannot find album.</p> <?php endif;?> <?php echo $this->render('footer.phtml'); ?>

Defeitos
Se voc est tendo problemas ao executar outra ao diferente de index/index, ento o problema que o roteador est incapaz de determinar em qual subdiretrio seu website est. Das minhas investigaes, isso normalmente acontece quando a url para seu website difere do caminho para o diretrio raz do servidor web. Se o cdigo padro no funcionou para voc, ento voc deve setar a varivel $baseURL para o valor correto do seu servidor: zf-tutorial/index.php
... // setup controller $frontController = Zend_Controller_Front::getInstance(); $frontController->throwExceptions(true); $frontController->setBaseUrl('/meusubdiretorio/zf-tutorial'); $frontController->setControllerDirectory('./application/controllers'); ...

Voc dever substituir '/meusubdiretorio/zf-tutorial/' pela URL correta para o index.php. Por exemplo, se seu index.php http://localhost/~ralle/zf_tutorial/index.php ento o valor correto para $baseUrl '/~ralle/zf_tutorial/'.

Concluso
Isto conclui nossa viso geral construindo uma aplicao MCV simples, mas completamente funcional usando o Zend Framework. Eu espero que voc tenha achado interessante e

informativo. Se voc achou que algo est errado, por favor, me envie um email para: rob@akrabat.com! Este tutorial mostrou apenas o bsico do Zend Framework; ainda existem muitas classes a serem exploradas. Voc realmente deveria ir e ler o manual (http://framework.zend.com/manual) e olhar o wiki (http://framework.zend.com/wiki) para mais introspeces! Se voc est interessado no desenvolvimento do framework, ento o wiki de desenvolvimento (http://framework.zend.com/developer) o seu lugar.

Você também pode gostar