Upload
eparateste
View
68
Download
0
Embed Size (px)
DESCRIPTION
Zend Framework book
Citation preview
5/27/2018 Zend Gramework
1/67
5/27/2018 Zend Gramework
2/67
Sobre o Autor
Elton Lus Minetto possui graduao em Cincia de Computaopela Unochapec e especializao em Cincia da Computaopela UFSC/UNOESC. Trabalha com PHP/MySQL desde 2000,com Linux desde 1997 e com MacOSX desde 2007. autor dolivro Frameworks para Desenvolvimento em PHP, da editoraNovatec e co-autor do livro Grid Computing in Research andEducation, publicado pela editora IBM/Redbooks, EUA.
Atualmente scio 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
http://eminetto.me/http://eminetto.me/http://www.coderockr.com/http://www.coderockr.com/5/27/2018 Zend Gramework
3/67
..............................................................Introduo 5.............................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 vises 20.........................................................Formulrios
23.................................................................Enviando arquivos 26
.........................................................Herana de formulrios 29................................................................................Subforms 30
...............................................Criando um CRUD 31....................................................................................Desafio 34
....................................Organizando a aplicao 34.........................................................Roteamento 37........................................................Autenticao 38
.............................................Controle de acesso 42...........................................................Navegao 47
5/27/2018 Zend Gramework
4/67
............................................................Paginao 49...................................................................Cache 52
............................................................Tradues 57.................................................Enviando e-mails 59
...................................Diagnstico da aplicao 63..................................................................................Zend_log 63
....................................................................Zend_Db_Profiler 65............................................................Concluso 67
5/27/2018 Zend Gramework
5/67
Introduo
Como a idia deste livro ir direto ao ponto, vou fazer isso j naintroduo.
A idia desse livro no explicar a teoria e filosofia do PHP, daorientao a objetos, as maravilhas dos design patterns, etc.Existem timos livros e sites que podem lhe ajudar a entendertodos os conceitos envolvidos aqui. Entre os livros eu possoindicar:
PHP Profissional. Alexandre Altair de Melo / Mauricio G. F.Nascimento. Editora Novatec
PHP Programando com Orientao a Objetos. PabloDallOglio. Editora Novatec
Zend Framework Componentes Poderosos para PHP. FlvioGomes da Silva Lisboa. Editora Novatec
Zend Framework em Ao. Rob Allen, Nick Lo, StevenBrown. Editora Alta Books.
Os trs primeiros so escritos por autores brasileiros e so livrosde grande importncia e didtica. O ltimo um clssico etambm muito bom.O foco desde livro ser um guia de desenvolvimento dasprincipais funcionalidades do Zend Framework. Ele iniciou comouma apostila para cursos que venho ministrando nos ltimos trsou quatro anos, ento algo que venho testando e alterandocontinuamente.Esta a segunda edio deste e-book. Nesta edio procurei
fazer uma atualizao nos cdigos e melhoria na explicao dealguns conceitos.Espero que lhe seja til como tem sido para mim.
5/27/2018 Zend Gramework
6/67
Instalando o Zend Framework
Instalar o Zend Framework uma tarefa simples.
O primeiro passo verificar os seus requisitos bsicos: umservidor web com suporte a reescrita de URLs (Apache serusado nestes exemplos) e o PHP 5.2.4 ou superior.No arquivo de configurao do Apache basta adicionar as linhasabaixo, ou alter-las para refletir o seguinte:
LoadModule rewrite_module modules/mod_rewrite.so
AddModule mod_rewrite.c
AllowOverride all
https://gist.github.com/987319
Isto indica ao servidor que ele deve carregar o mdulo quepermite a reescrita de URLs (mais exemplos nos prximostpicos) e permite o uso de configuraes em arquivos especiais.
Agora basta fazer o download do framework, no site
http://framework.zend.com
No momento da escrita deste livro a verso mais atual era a1.11.11. No site possvel escolher entre trs opes paradownload: a verso com o Zend Server, a verso Full e a versoMinimal do framework. A primeira indicada se voc quer asoluo completa, com um servidor Apache e o MySQL jconfigurados. A verso full possui, alm do framework,
documentao, testes e demos. E a verso minimal formadaapenas pelo framework. Geralmente a verso minimal a maisindicada.Depois de descompactar o arquivo possvel visualizar a seguinteestrutura (para a verso Minimal):
bin/ scripts para a criao de projetos
LICENSE.txt - uma cpia da licena usada pelo framework
README.txt - instrues sobre instalao e documentao
VERSION.txt texto sobre a verso do framework
library/ - neste diretrio encontra-se o framework
INSTALL.txt - instrues de instalao
https://gist.github.com/987319https://gist.github.com/987319https://gist.github.com/9873195/27/2018 Zend Gramework
7/67
O diretrio library deve ser copiado para o diretrio htdocs de seuservidor Apache. E pronto! O Zend Framework est pronto parauso.
Definindo o projeto
Na minha opinio a nica forma de aprender uma novaferramenta, linguagem, sistema operacional, quando vocrealmente precisa resolver algum problema com ela. Pensandonisso, esse livro baseado na construo de um aplicativo: umblog.
Mas um blog? Por alguns motivos: um problema fcil de se entender. Todo mundo sabe como
um blog funciona, seus requisitos e funcionalidades. Ento afase de requisitos do projeto fcil de completar
um blog apresenta um grande nmero de funcionalidadescomuns a vrios outros sites, como mdulos, controle deacesso e permisses, upload de arquivos, tratamento deformulrios, cache, tradues, integrao com serviosexternos, etc.
a grande maioria dos frameworks possui um exemplo comodesenvolver um blog usando X, ento fica mais fcil paracomparao se voc j estudou algum outro frameworkcomo CakePHP, CodeIgniter ou mesmo Ruby on Rails
Modelagem
Agora que o convenci (ou no) de como desenvolver um blog
pode lhe ajudar a entender o Zend Framework, vamos mostrar amodelagem das tabelas:
5/27/2018 Zend Gramework
8/67
Simples, como deveria ser.Usando alguma ferramenta, como o PHPMyAdmin, SequelPro, ouo bom e velho terminal, possvel criar a estrutura do bancousando os comandos SQL abaixo:
CREATEDATABASEblog;
GRANTALLprivileges ONblog.*TOzend@localhost IDENTIFIEDBY
'zend';
USEblog;
CREATE TABLEIFNOTEXISTS`users`(
`id`INTNOTNULLAUTO_INCREMENT, `username`VARCHAR(200)NOTNULL, `password`VARCHAR(250)NOTNULL, `name`VARCHAR(200)NULL, `valid`TINYINT NULL, `role`VARCHAR(20)NULL, PRIMARYKEY(`id`))ENGINE =InnoDB;
CREATE TABLEIFNOTEXISTS`posts`(
`id`INTNOTNULLAUTO_INCREMENT, `title`VARCHAR(250)NOTNULL, `description`TEXT NOTNULL, `post_date`TIMESTAMPNOTNULLDEFAULTCURRENT_TIMESTAMP, PRIMARYKEY(`id`))ENGINE =InnoDB;
CREATE TABLEIFNOTEXISTS`comments`(
`id`INTNOTNULLAUTO_INCREMENT, `post_id`INTNOTNULL, `description`TEXT NOTNULL, `name`VARCHAR(200)NOTNULL, `email`VARCHAR(250)NOTNULL,
5/27/2018 Zend Gramework
9/67
`webpage`VARCHAR(200)NOTNULL, `comment_date`TIMESTAMPNULL, PRIMARYKEY(`id`,`post_id`), INDEX`fk_comments_posts`(`post_id`ASC), CONSTRAINT`fk_comments_posts` FOREIGNKEY(`post_id`) REFERENCES`posts`(`id`) ONDELETENO ACTION ONUPDATENO ACTION)ENGINE =InnoDB;
https://gist.github.com/987325
Estrutura do projeto
Vamos agora usar a ferramenta de gerao de projetos do ZendFramework.No diretrio bin do framework existem os arquivo zf.bat (Windows)e zf.sh (Linux/Mac OS X). preciso que este arquivo e oexecutvel do PHP estejam no caminho dos executveis (PATH)do seu sistema operacional, ou execut-lo pelo caminho ondevoc salvou o framework.
Para criar o projeto vamos executar:./ZendFramework-1.11.11-minimal/bin/zf.sh create project blog
O diretrio blog foi criado com o contedo:
application - diretrio da aplicao
Bootstrap.php - bootstrap da aplicao
configs - arquivos de configurao
controllers - controladores
models - modelos views - vises
docs - documentaes
library - aqui devemos copiar o framework
public - diretrio de arquivos pblicos
tests - testes unitrios
Configurando o Apache
https://gist.github.com/987325https://gist.github.com/987325https://gist.github.com/9873255/27/2018 Zend Gramework
10/67
Vamos tambm configurar um VirtualHost no Apache para facilitaros testes da aplicao. No arquivo httpd.conf (ou apache.conf)adicionar o seguinte (procure no arquivo docs/README.txt doprojeto)
DocumentRoot "/caminho_htdocs/blog/public"
ServerName blog.local
# This should be omitted in the production environment
SetEnv APPLICATION_ENV development
Options Indexes MultiViews FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
necessrio alterar os caminhos nas opes DocumentRoot eDirectory para refletirem o caminho correto em sua mquina.
preciso tambm alterar o arquivo hosts do sistema operacionalpara adicionar o endereo do blog.local. No Linux e Mac OS X,alterar o /etc/hosts e adicionar a linha:
127.0.0.1 blog.local
No Windows o arquivo que deve ser alterado o c:\windows\system32\drivers\etc\hosts e a linha a ser adicionada igual acitada acima.
Bootstrap
No Zend Framework, existe um componente importante, chamadode Bootstrap que responsvel por receber todas as requisies,
5/27/2018 Zend Gramework
11/67
configurar o necessrio (por exemplo: sesses, conexo combanco de dados, cache, etc) e invocar o controlador especificadopela URL que o usurio solicitou. Vou tentar explicar isso na formade uma imagem:
O usurio faz uma requisio ao Apache, que invoca o Bootstrap
(na imagem o index.php). Este por sua vez faz a configuraonecessria e passa a execuo para o controlador. O controladorfaz seu trabalho especfico, podendo usar cdigos contidos nosmodelos e formatar vises que sero mostradas ao usurio. Aofinal do processo do controlador, o Bootstrap volta a assumir efinaliza a requisio.Esta forma como o Zend Framework trabalha muito interessantepois nos permite diversas flexibilidades e configuraes. Sedeterminada configurao ou varivel deve ser acessvel a todos
os pontos de nossa aplicao (controladores, modelos e vises)ela pode ser escrita no Bootstrap, pois sabemos que todaexecuo ir obrigatoriamente passar por ela. Outra vantagem que se caso ocorra alguma exceo (Exceptions da linguagemPHP) que no for tratada por um controlador o Bootstrap irreceb-la e podemos ter um ponto nico no sistema para capturare tratar erros.Todo este processo funciona da seguinte forma: o arquivoindex.php cria uma instncia da classe Zend_Application que usa
a classe Bootstrap contida no Bootstrap.php. Ao ser inicializada, a
5/27/2018 Zend Gramework
12/67
aplicao ir executar todos os mtodos cujo nome iniciem com_init. Podemos criar nosso Bootstrap inicial da seguinte forma:
5/27/2018 Zend Gramework
13/67
Nos prximos tpicos vamos adicionando tens ao Bootstrap.Um novo conceito apresentado no cdigo acima oZend_Registry. O registro uma forma de armazenarmos objetosou variveis para que estes estejam acessveis em toda a
aplicao. um mecanismo elegante para substituir o uso devariveis 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 usurio invocou. Funciona daseguinte 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 domdulo default (que o mdulo padro, caso exista) e tentarinvocar um mtodo chamado showAction (a action) passando umparmetro chamado id, com valor 1.
O segundo link vai acessar o controlador IndexController dentrodo mdulo admin (que especificado na url) e tentar invocar ummtodo chamado showAction (a action) passando um parmetro
chamado id, com valor 1.Todos os controladores so classes que extendem uma classechamada Zend_Controller_Action e devem estar em um arquivocujo nome termine em Controller.php. Exemplo. Para criarmos osarquivos que atendam os exemplos acima, precisamos criar:
application/controllers/IndexController.php
e
http://blog.local/admin/post/show/id/1http://base/http://blog.local/admin/post/show/id/1http://blog.local/admin/post/show/id/1http://blog.local/post/show/id/1http://blog.local/post/show/id/1http://base/http://base/5/27/2018 Zend Gramework
14/67
application/modules/admin/controllers/IndexController.php
O contedo do primeiro seria:
5/27/2018 Zend Gramework
15/67
estes devem ser armazenados no diretrio models. Todos osmodelos so classes PHP que extendem a classeZend_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 dodatabase, caso sejam diferentesAgora vamos criar o primeiro model, o arquivo models/Users.php
Users.php
5/27/2018 Zend Gramework
16/67
Comments.php
5/27/2018 Zend Gramework
17/67
Com essa funcionalidade podemos facilmente, a partir de um blogrecuperar seus comentrios. Por exemplo, podemos usar umcdigo similar ao abaixo, em um controlador, para recuperar oscomentrios (vamos ver mais exemplos sobre o uso dos models e
dos controllers nos prximos tpicos)
//cria uma instncia do modelo Posts
$posts=newApplication_Model_Posts;
//busca detalhes do post com id = 1
$post=$posts->fetchRow("id = 1");
//busca todos os comentrios deste post
$comments=$post->findDependentRowset('Comments');
Tambm possvel realizar o processo inverso. Digamos que euprecise buscar os dados do post relacionado a um determinadocomentrio:
//cria uma instncia do modelo Comments
$comments=newApplication_Model_Comments;
//busca detalhes do comentrio com id = 1
$comment=$comments->fetchRow('id = 1');
//busca os dados do post relacionado a este comentrio
$post=$comment->findParentRow('Posts');
O framework tambm fornece o suporte a relacionamentosmuitos para muitos, que no faz parte do nosso exemplo, maspode se r v i s to na documen tao ofic ia l (m todofindManyToManyRowset):
http://framework.zend.com/manual/en/zend.db.table.relationships.html
Trabalhando com modelos e queries
O Zend Framework fornece trs formas de acessarmos os dadosde uma base de dados: usando models, usando oZend_Db_Select para gerar queries ou escrevendo a query sem ouso de objetos.
Exemplos usando Models
Para recuperarmos todos os registros na tabela Posts:
http://framework.zend.com/manual/en/zend.db.table.relationships.htmlhttp://framework.zend.com/manual/en/zend.db.table.relationships.html5/27/2018 Zend Gramework
18/67
$posts=newApplication_Model_Posts;
$data=$posts->fetchAll();
Para recuperarmos apenas o registro com id = 1$posts=newApplication_Model_Posts;
$data=$posts->fetchRow("id = 1")
Para fazermos insert de um registro
$posts=newApplication_Model_Posts;
$data=array(
'title'=>'Ttulo 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
$posts=newApplication_Model_Posts;
$data=array(
'title'=>'Novo ttulo do post',);$posts->update($data,"id = $id");//update do post com id especfico
Para fazermos delete de um registro
$posts=newApplication_Model_Posts;
$posts->delete("id = $id");
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 consultascomplexas sem a necessidade de escrever cdigo SQL, e simutilizando objetos.O construtor do Zend_Db_Select necessita uma conexo com umbanco de dados. Podemos buscar a conexo com a base dedados que criamos no Bootstrap.php:
$db=Zend_Registry::get('db');$select=newZend_Db_Select($db);
http://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/array5/27/2018 Zend Gramework
19/67
Exemplos de uso
Consulta simples, como um SELECT * FROM 'users'
$select=newZend_Db_Select($db);
$select->from('users');
$select->limit(10);
$select->order('id desc');
$rs=$select->query();
$data=$rs->fetchAll()
Consulta com insero de clausula WHERE, como um SELECT *FROM 'users' WHERE 'id' > 10:
$select=newZend_Db_Select($db);
$select->from('users');
$select->where('id > ?',10);
$rs=$select->query();
$data=$rs->fetchAll()
Consulta com seleo de campos e clusula WHERE, como umSELECT id, name FROM 'users' WHERE id > 10:
$select=newZend_Db_Select($db);
$select->from('users');
$select->columns('id, name');
$select->where('id > ?',10);
$rs=$select->query();
$data=$rs->fetchAll()
Consulta com seleo de campos e clusula WHERE e INNERJOIN, como um SELECT 'users'. 'id', 'users'. 'name', 'pictures'.
'address' FROM `users` INNER JOIN `pictures` ON`pictures`.`user_id` = `users`.`id` WHERE users.id > 10:
$select=newZend_Db_Select($db);
$select->from('users');
$select->columns('users.id, users.name, pictures.address');
$select->joinInner('picures','picures.user_id = user.id');
$select->where('users.id > ?',10);
$rs=$select->query();
$data=$rs->fetchAll()
5/27/2018 Zend Gramework
20/67
Em qualquer momento possvel imprimir a consulta que foigerada. til para fins de debug
echo$select;
Executando consultas SQL
Para executar consultas SQL simples:
$sql="select * from posts";
$stmt=$db->query($sql);
$this->view->data=$stmt->fetchAll();
Layout e vises
No contexto de uma aplicao desenvolvida com o ZendFramework, uma viso uma poro de cdigo que servisualizada pelo usurio. HTML, CSS, JavaScript, imagens, etc. papel do controlador acessar e processar dados (como osvindos da camada de modelo) e prepar-los para seremvisualizados pelo usurio, atravs da viso. Um arquivo de viso
nada mais do que um arquivo PHP com a extenso .phtml e cujafuno bsica imprimir (usando echo por exemplo) os dadosenviados pelo controlador. No nosso exemplo, vamos analisar ocdigo do controlador IndexController, cujo contedo est noarquivoapplication/controllers/IndexController.php
5/27/2018 Zend Gramework
21/67
indexAction() a classe ir tentar encontrar um arquivo de viso,chamado index.phtml (este um comportamento herdado daclasse Zend_Controller_Action) em um diretrio especfico, o
views/scripts/index/index.phtml
Todos os arquivos de viso do controlador IndexController devemser criados no diretrio index dentro do views/scripts.O contedo do arquivo index.phtml simplesmente
Agora vamos trabalhar com um novo conceito, os layouts. Para
isso vamos analisar o wireframe do nosso blog:
Em todas as pginas iremos ter um ttulo, uma imagem e umrodap, com informaes sobre o autor, copyright, etc. A nicainformao que ir mudar o contedo das pginas. Na pginainicial teremos os ltimos posts do blog, opes de incluir eexcluir, posts, etc. Mas o cabealho e o rodap permanecem osmesmos. Para facilitar este tipo de construo o Zend Frameworkpossui o conceito de layouts. Precisamos ativar o recurso de
layouts no nosso projeto, digitando o comando:
5/27/2018 Zend Gramework
22/67
zf enable layout
Isto indica ao framework que o arquivo de layout chama-sedefault.phtml e encontra-se no diretrio do projeto:
application/layouts/scripts/layout.phtml
Seu contedo :
Blog
//mostra o contedo da pgina
echo $this->layout()->content;
?>
https://gist.github.com/1473182
A linha mais importante deste arquivo a
echo$this->layout()->content;
que ir gerar o contedo das vises sendo executadas. Noexemplo anterior, o contedo da viso views/scripts/index/index.phtml gerada por esta linha.No arquivo default.phtml onde deve ser adicionada toda a partede CSS, e onde iramos colocar nosso cabealho e rodap paraser apresentado por toda a aplicao.
O resultado pode ser visto ao acessar a URL
http://blog.local/
https://gist.github.com/1473182https://gist.github.com/1473182https://gist.github.com/1473182https://gist.github.com/1473182https://gist.github.com/1473182https://gist.github.com/1473182https://gist.github.com/1473182http://blog.local/http://blog.local/https://gist.github.com/1473182https://gist.github.com/14731825/27/2018 Zend Gramework
23/67
Uma observao. Se no especificarmos qual o controlador naURL o Bootstrap vai automaticamente procurar o controladorIndexController e a action indexAction. Ento acessar
http://blog.local
equivalente a acessar
http://blog.local/index/index
Formulrios
O Zend_Form um componente que permite que formulriossejam criados e mantidos usando-se objetos, aumentandoprodutividade e mantendo um padro de desenvolvimento. possvel tambm com o Zend_Form, a implementao deformulrios com herana, ou seja, voc tem um formulriogenrico (ex: Application_Form_Usuario) que pode ser utilizadopara criao de outros (ex: Application_Form_UsuarioAdmin) quepossuiriam apenas alguns campos adicionais alm do form
padro.Ele tambm possui componentes que permitem a utilizao detodos os Filters e Validators do Zend, bem como a implementaode Componentes personalizados.Teremos inicialmente dois formulrios, o de login e o de cadastro/alterao de novos posts (que ser usado pelo administrador).Neste captulo iremos definir e mostrar na viso os formulrios,deixando a lgica da manipulao dos mesmos para os tpicos
posteriores.
Vamos criar o primeiro formulrio, o de login com o comando:
zf create form Login
O arquivo forms/Login.php:
5/27/2018 Zend Gramework
24/67
class Application_Form_Loginextends Zend_Form
{
public function init() { //nome do formulrio $this->setName('Login'); //elemento para o campo username $username= new Zend_Form_Element_Text('username'); //configurar o label, dizer q obrigatrio, adicionar umfiltro e um validador
$username->setLabel('Login') ->setRequired(true) ->addFilter('StripTags') ->addValidator('NotEmpty'); //elemento para a senha $password= new Zend_Form_Element_Password('password'); $password->setLabel('Senha') ->setRequired(true) ->addFilter('StripTags') ->addValidator('NotEmpty'); //boto de submit $submit= new Zend_Form_Element_Submit('submit'); $submit->setLabel('Entrar'); $submit->setAttrib('id', 'Entrar') ->setIgnore(true);
//exemplo de class css
//$submit->setAttrib('class', 'verde buttonBar'); //adicionar os campos ao formulrio $this->addElements(array($username, $password, $submit)); //action e method $this->setAction('/auth/index')->setMethod('post'); }
}
https://gist.github.com/1455143
Todos os formulrios so classes PHP que extendem a classeZend_Form. Aps criarmos os campos $username e $passwordfazemos a configurao dos mesmo, indicando o label, se soobrigatrios (setRequired), adicionamos filtros (addFilter, no
exemplo o filtro StripTags que remove tags html do contedo) e
https://gist.github.com/1455143https://gist.github.com/1455143https://gist.github.com/1455143https://gist.github.com/14551435/27/2018 Zend Gramework
25/67
validadores (o NotEmpty garante que o campo no vai ser aceitose estiver vazio).Precisamos agora alterar o controlador para que ele faa ainstanciao do novo objeto de formulrio. Para realizarmos um
teste vamos alterar o controlador IndexController.php eadicionamos as linhas abaixo, no mtodo indexAction.
//cria um novo formulrio
$this->view->form=newApplication_Form_Login;
No nosso arquivo de viso (views/index/index.phtml) iremosmostrar o nosso formulrio:
Basta imprimir o formulrio na view, e todo o HTML ser gerado,de acordo com as configuraes do arquivo forms/Login.php.Podemos fazer a mesma coisa com o formulrio de cadastro deposts.Vamos criar a classe do formulrio de insero/alterao de posts.O arquivo forms/Post.php ficou da seguinte maneira:
zf create form Post
5/27/2018 Zend Gramework
26/67
$submit->setLabel('Adicionar')->setIgnore(true); $this->addElements(array($id, $titulo, $texto, $submit)); //action e method $this->setAction('/post/create')->setMethod('post'); }
}
https://gist.github.com/1335179
A nica novidade neste formulrio so os elementos textarea ehidden, que geram os seus correspondentes em html. Maisadiante iremos voltar a trabalhar com estes formulrios, o de logine o responsvel por criar novos posts no blog.
Enviando arquivos
Outra funcionalidade comum a necessidade de enviar arquivosvia formulrios. Apesar de no fazer parte do nosso blog, vamosfazer um exemplo usando o Zend_Form. Vamos criar um novoform:
zf create form Album
O contedo do arquivo forms/Album.php:
5/27/2018 Zend Gramework
27/67
$submit= new Zend_Form_Element_Submit('submit'); $submit->setLabel('Enviar'); $submit->setName('submit'); //exemplo de class css $this->addElements(array($title, $file, $submit)); //action e method $this->setAction('/album')->setMethod('post'); $this->setAttrib('enctype', 'multipart/form-data'); }}
https://gist.github.com/1468851
Neste formulr io demonstrado o uso da c lasseZend_Form_Element_File, com seus validadores especficos,definindo o tamanho mximo do arquivo e suas extensespermitidas.Para podermos usar este form vamos criar o controladorAlbumController.php (zf create controller Album) com o contedoabaixo:
5/27/2018 Zend Gramework
28/67
//verifica se o formulrio est vlido //de acordo com os validadores do Zend_Form if ($form->isValid($formData)) { $adapter= $form->arq->getTransferAdapter();
//indica o destino dos arquivos temporrios
$adapter->setDestination('/tmp'); try {//recebe o arquivo
$adapter->receive();} catch (Zend_File_Transfer_Exception $e) {
echo $e->getMessage();
}
//nome do arquivo $name= $adapter->getFileName(); //tamanho
$size= $adapter->getFileSize(); //tipo $mimeType=
$adapter->getMimeType(); // somenete mostra os detalhes do
arquivo echo "Nome do arquivo enviado: $name", "
"; echo "Tamanho do arquivo: $size", "
"; echo "Tipo: $mimeType", "
"; // Novo nome do arquivo $renameFile= 'NovoNome.jpg';
$fullFilePath= '/tmp/'.$renameFile; // renomeia usando o Zend
Framework $filterFileRename=
newZend_Filter_File_Rename(array('target'=> $fullFilePath,
'overwrite'
=> true));
$filterFileRename->filter($name); }//se o formulrio est invlido else {
// Mostra os erros e popula o form com os dados
corretos
$form->populate($formData);}
} else {
//ainda no foi submetido dados
} $this->view->form= $form;
}
5/27/2018 Zend Gramework
29/67
}
https://gist.github.com/1468878
E finalmente, a viso views/scripts/album/index.phtml:
Nesse exemplo possvel visualizar a facilidade de uso e do ZendFramework para tratar arquivos enviados pelo usurio.
Herana de formulrios
possvel criarmos heranas de formulrios.Vamos definir um formulrio base, chamado PessoaForm. Estaclasse possui os campos bsicos, que todos os formulrios tero.Ao definirmos esta classe como abstrata garantimos que odesenvolvedor precisa extend-la antes de usar algum formulrio,pois classes abstratas no podem ser instanciadas.
5/27/2018 Zend Gramework
30/67
5/27/2018 Zend Gramework
31/67
$endereco=newZend_Form_SubForm();
$endereco->addElements(array(
newZend_Form_Element_Text('cidade',array( 'required' =>true, 'label' =>'Cidade:', 'filters' =>array('StringTrim','StringToLower'), 'validators'=>array( 'Alnum', array('Regex', false, array('/^[a-z][a-z0-9]{2,}$/')) ) )), newZend_Form_Element_Text('estado',array( 'required' =>true, 'label' =>'Estado:', 'filters' =>array('StringTrim'), 'validators'=>array( 'NotEmpty', array('StringLength',false,array(6)) ) )), ));
$this->addSubForms(array('endereco'=>$endereco));
https://gist.github.com/987377
Criando um CRUD
Vamos agora usar o que aprendemos para criar o CRUD (Create,Replace, Update, Delete) de um post.
O primeiro passo criamos o controller PostController e asactions. Para isso podemos usar os comandos:
zf createcontroller Post
zf create action create Post
zf create action retrievePost
zf create action update Post
zf create action delete Post
Agora vamos criar cdigo da primeira action, o retrieveAction(),que vai nos mostrar os posts cadastrados. O cdigo :
https://gist.github.com/987377http://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttps://gist.github.com/987377https://gist.github.com/9873775/27/2018 Zend Gramework
32/67
public function retrieveAction()
{
$posts = new Application_Model_Posts();
$this->view->posts = $posts->fetchAll();
}
E o arquivo views/scripts/post/retrieve.phtml:
Posts
Adicionar
5/27/2018 Zend Gramework
33/67
if ($form->isValid($this->_request->getPost())) { $id = $post->insert($form->getValues()); $this->_redirect('post/retrieve'); }//form invalido else { // Mostra os erros e popula o form com osdados $form->populate($form->getValues());
}
} $this->view->form = $form; }
https://gist.github.com/1335245
E e o views/scripts/post/create/phtml:
Vamos agora reutilizar o Application_Form_Post para realizarmosa atualizao de um post. Para isso criamos o seguinte cdigo noupdateAction() :
public function updateAction()
{ $form = new Application_Form_Post(); $form->setAction('/post/update'); $form->submit->setLabel('Alterar'); $posts = new Application_Model_Posts();
//tem dados
if ($this->_request->isPost()) { //form valido if ($form->isValid($this->_request->getPost())) { $values = $form->getValues(); $posts->update($values, 'id = ' .$values['id']);
$this->_redirect('post/retrieve'); }//form invalido else { // Mostra os erros e popula o form com osdados
$form->populate($form->getValues());}
} else { //no tem dados $id = $this->_getParam('id'); $post = $posts->fetchRow("id =$id")->toArray();
https://gist.github.com/1335245https://gist.github.com/1335245https://gist.github.com/1335245https://gist.github.com/13352455/27/2018 Zend Gramework
34/67
$form->populate($post); } $this->view->form = $form; }
https://gist.github.com/1335264
O views/scripts/post/update.phtml exatamente igual aocreate.phtml.Com esse cdigo podemos ver o re-aproveitamento de umformulrio, somente mudando alguns comportamentos.
E o mtodo final, o deleteAction:
public function deleteAction()
{
$posts = new Application_Model_Posts(); $id = $this->_getParam('id'); $posts->delete("id = $id"); $this->_redirect('post/retrieve'); }
Desafio
Fazer o CRUD das tabelas users e comments
Organizando a aplicao
Agora que j conhecemos alguns conceitos importantes do ZendFramework vamos organizar melhor nossa aplicao. O primeiropasso pensarmos na estrutura dos nossos controllers e no fluxo
da aplicao:
https://gist.github.com/1335264https://gist.github.com/13352645/27/2018 Zend Gramework
35/67
Redirect
PostController:retrieveAction
IndexController:indexAction
Link
AuthController:indexAction
Redirect
PostController:retrieveAction
O IndexController::indexAction vai somente nos direcionar para aaction retrieve do controller PostController, que nos mostra todosos posts cadastrados na base de dados. Na view post/retrieve.phtml vamos ter um link para a action index doAuthController, que vai ser responsvel pela autenticao, usandoo Application_Form_Login criado anteriormente. Aps aautenticao ser feita com sucesso vamos retornar aoretrieveAction do PostController, onde vamos ter acesso aos
outros mtodos do CRUD.
Vamos ento alterar o mtodo indexAction do IndexController:
public function indexAction()
{
$this->_redirect('/post/retrieve');}
5/27/2018 Zend Gramework
36/67
Vamos tambm adicionar o link para o AuthController no nossoarquivo post/retrieve.phtml:
Fazer login
No prximo tpico iremos criar o AuthController para fazer aautenticao dos nossos usurios.
Outro ponto que podemos melhorar a criao de um controladorbase para a nossa aplicao, de onde todos os outroscontroladores (IndexController, PostController e AuthController)vo herdar. Isso uma prtica comum e muito til pois podemoscriar mtodos que sero vistos por todos os controladores na
nossa aplicao. Inicialmente vamos precisar criar um diretriochamado Blog dentro do library e dentro dele um novo diretriochamado Controller. Dentro deste vamos criar o Action.php. Aestrutura deve ficar da seguinte forma:
O contedo do arquivo Action.php :
5/27/2018 Zend Gramework
37/67
public function _initLoader()
{
$loader = Zend_Loader_Autoloader::getInstance(); $loader->registerNamespace('Blog_');}
Agora precisamos mudar os nossos controllers para herdarem oBlog_Controller_Action:
class IndexController extends Blog_Controller_Action
class PostController extends Blog_Controller_Action
Roteamento
Roteamento o processo de converter uma URL em uma ao aser executada. A rota default traduz URLs no formato citadoanteriormente. Rotas adicionais podem ser criadas, geralmentepara disponibilizar URLs mais fceis de serem compreendidas oumais curtas. Por exemplo, poderamos criar uma rota para que aURL atualizar/142 fosse mapeada da mesma forma que post/update/id/142.
Para fazer isso podemos adicionar as linhas abaixo noapplication.ini
;routes
resources.router.routes.update.route = /atualizar/:id
resources.router.routes.update.defaults.controller = post
resources.router.routes.update.defaults.action = update
resources.router.routes.excluir.route = /excluir/:id
resources.router.routes.excluir.defaults.controller = postresources.router.routes.excluir.defaults.action = delete
Tambm podemos fazer de outra forma, criando um mtodo_initRoutes() no Bootstrap.php. Algo como:
/**
* Inicializa as rotas
*
* @return void
* @author Elton Minetto*/
5/27/2018 Zend Gramework
38/67
public function _initRoutes()
{
$updateRoute = new Zend_Controller_Router_Route( 'atualizar/:id', array( 'controller' => 'post', 'action' => 'update' ) ); $deleteRoute = new Zend_Controller_Router_Route( 'excluir/:id', array( 'controller' => 'post', 'action' => 'delete' ) );
$router = Zend_Controller_Front::getInstance()->getRouter();
$router->addRoute('updateRoute', $updateRoute);$router->addRoute('deleteRoute', $deleteRoute);
}
https://gist.github.com/1469916
Podemos criar diversas rotas especiais, usando expressesregulares e outras opes avanadas. No site da documentaodo framework existem diversos exemplos, mas na maioria dasvezes as rotas simples como mostrada neste exemplo sosuficientes
Autenticao
Nosso blog vai ter trs tipos de usurios, o visitante normal, umredator e um tipo especial, o administrador. Os administradorespodem adicionar novos posts no blog, alter-los e exclu-los (oCRUD de Post que fizemos no captulo anterior). O redator vaipoder adicionar e alterar posts, mas no exclu-los.
Para isso precisamos determinar uma forma de identificar ousurio, para sabermos se ele vlido, e no prximo tpicoiremos ver como controlar seu nvel de acesso (administrador ou
redator). Iremos usar o formulrio Application_Form_Login criado
https://gist.github.com/1469916https://gist.github.com/14699165/27/2018 Zend Gramework
39/67
anteriormente, em conjunto com um componente do frameworkchamado Zend_Auth.
O Zend_Auth fornece uma API para autenticao e inclui
adaptadores para os cenrios de uso mais comuns: LDAP, bancode dados, HTTP, OpenID. E o desenvolvedor pode criar seusprprios adaptadores extendendo os j existentes.
Vamos criar o AuthController usando o Zend Tool.
zf create controller Auth
O cdigo final:
5/27/2018 Zend Gramework
40/67
$authAdapter->setIdentity($formData['username'])-
>setCredential($formData['password']);
//tenta fazer a autenticao $result= $auth->authenticate($authAdapter); //verifica o resultado $session= Zend_Registry::get('session'); switch ($result->getCode()) { caseZend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND:
$session->erro= 'Usurioinvlido';
$form->populate($formData);break;
caseZend_Auth_Result::FAILURE_CREDENTIAL_INVALID:
$session->erro= 'Senhainvlida';
$form->populate($formData);break;
case Zend_Auth_Result::SUCCESS: $data= $authAdapter->getResultRowObject();
$session->role= $data->role; //guarda a role do usurio
$this->_redirect('/post/retrieve'); break; default: /** em caso de outro tipo defalhas **/
break; }
}
else { // Mostra os erros e popula o form com osdados
$form->populate($formData);} }
$this->view->form= $form; }
}
https://gist.github.com/1449550
https://gist.github.com/1449550https://gist.github.com/1449550https://gist.github.com/1449550https://gist.github.com/1449550https://gist.github.com/1449550https://gist.github.com/1449550https://gist.github.com/1449550https://gist.github.com/1449550https://gist.github.com/1449550https://gist.github.com/14495505/27/2018 Zend Gramework
41/67
O Zend_Auth simples de ser usado, como possvel ver nocdigo acima. Com poucas linhas configurada a forma deautenticao (com uma tabela do banco de dados) e faz-se a
validao. Caso a validao tenha ocorrido com sucesso ascredenciais do usurio so automaticamente armazenadas nasesso. Tambm armazenamos na sesso a role do usurio, parausarmos posteriormente.
Precisamos alterar o cdigo da nossa viso, o arquivo views/scripts/auth/index.phtml, adicionando o cdigo abaixo:
Vamos aproveitar tambm e mudar o nosso layout, paramostrarmos uma opo para o usurio fazer logout do sistema. Oarquivo layouts/scripts/layout.phtml ficou da seguinte forma:
Blog do Minetto
Sair
Fazer login
5/27/2018 Zend Gramework
42/67
?>
Copyleft @eminetto
https://gist.github.com/1449567
Vamos agora adicionar a funo de logout() no AuthController:
public function logoutAction() {
Zend_Auth::getInstance()->clearIdentity(); $this->_redirect('/');}
Como o layout agora controla se deve mostrar ou no o link pararealizar o login podemos remover o link que colocamos no views/scripts/post/retrieve.phtml (refatorar bom!)
Controle de acesso
Ns vimos anteriormente o uso do componente Zend_Auth. Estecomponente responsvel apenas pela autenticao dosusurios, sendo que ele no permite o controle de permisses aosrecursos do aplicativo. Esse papel responsabilidade docomponente Zend_Acl. ACL (Access Control List - lista de controlede acesso) uma soluo simples e flexvel para realizar ocontrole do acesso a determinados recursos.
Alguns conceitos so usados pelo Zend_Acl:
papel (role): um grupo de usurios
recurso (resource): algo a ser protegido
privilgio (privilege): o tipo de acesso exigido
O primeiro passo o planejamento dos tens citados acima. Nonosso projeto, do blog, vamos usar trs roles:
visitante: pessoas que no fizeram o login no sistema
https://gist.github.com/1449567https://gist.github.com/1449567https://gist.github.com/1449567https://gist.github.com/1449567https://gist.github.com/1449567https://gist.github.com/1449567https://gist.github.com/1449567https://gist.github.com/1449567https://gist.github.com/1449567https://gist.github.com/14495675/27/2018 Zend Gramework
43/67
redator: usurios que podem publicar e editar posts, masno apag-los
admin: usurios com todas as permisses de acesso
Vamos ter tambm trs recursos a proteger:
index: controlador IndexController
post: controlador PostController
auth: controlador AuthController
Os privilgios que iremos controlar so os mtodos doscontroladores citados.
O primeiro passo descrever os papis, recursos e privilgios nonosso arquivo de configurao, o application.ini:
;roles
acl.roles.visitante= null
acl.roles.redator= visitante
acl.roles.admin= redator
acl.resources[]= index
acl.resources[]= post
acl.resources[]= auth
;definir as acls no formato acl.permissao.role[] = controller.actionacl.allow.visitante[]= index.index
acl.allow.visitante[]= post.retrieve
acl.allow.visitante[]= auth.index
acl.allow.visitante[]= auth.logout
acl.allow.redator[]= post.create
acl.allow.redator[]= post.update
acl.allow.admin[]= post.delete
https://gist.github.com/1449742
Uma caracterstica interessante do Zend_Acl a possibilidade dasroles terem herana. Da forma como configuramos o redatorherda as configuraes do visitante e o admin herda asconfiguraes do redator. Isso facilita bastante a configurao. Aslinhas acl.resources[] e acl.allow.visitante[], por exemplo, vo sertransformadas em Arrays de objetos pelo Zend_Config. Podemos
https://gist.github.com/1449742https://gist.github.com/1449742https://gist.github.com/1449742https://gist.github.com/1449742https://gist.github.com/1449742https://gist.github.com/1449742https://gist.github.com/1449742https://gist.github.com/14497425/27/2018 Zend Gramework
44/67
tambm usar acl.deny.permissao.role[] caso queiramos negar oacesso a determinado recurso.
No nosso Bootstrap.php vamos adicionar as seguintes linhas de
cdigo, que so responsveis por ler o arquivo de configurao egerar as ACLs:
/**
* inicializa a acl
*
* @return void
* @author Elton Minetto
**/
protected function _initAcl()
{
$acl = new Zend_Acl; $config = Zend_Registry::get('config'); foreach($config->acl->roles as $role => $parent) { if($parent) $acl->addRole(new Zend_Acl_Role($role), $parent); else $acl->addRole(new Zend_Acl_Role($role)); } foreach($config->acl->resources as $r) { $acl->add(new Zend_Acl_Resource($r)); } if(isset($config->acl->allow)) { foreach($config->acl->allow as $role => $privilege) { foreach($privilege as $p) { $privilege = explode('.', $p); $acl->allow($role, $privilege[0],$privilege[1]);
} } } if(isset($config->acl->deny)) { foreach($config->acl->deny as $role => $privilege) { foreach($privilege as $p) { $privilege = explode('.', $p); $acl->deny($role, $privilege[0],$privilege[1]);
} } } Zend_Registry::set('acl',$acl);}
5/27/2018 Zend Gramework
45/67
https://gist.github.com/1449750
Agora vamos usar a nossa classe Blog_Controller_Action. Comosabemos que todos os controllers herdam dela vamos criar omecanismo de autenticao/autorizao neste local. O cdigo doarquivo ficou:
5/27/2018 Zend Gramework
46/67
https://gist.github.com/1449759
Desta forma todos os nossos controllers conhecem o controle deacesso.
Uma observao. Caso algum controller precise definir algo emseu mtodo init() necessrio sempre invocar tambm o init() daclasse pai (Blog_Controller_Action), como no exemplo:
public function init()
{
parent::init(); $this->posts = new Application_Model_Posts();
}
Assim as ACLs so respeitadas.
Vamos agora criar alguns usurios de teste na tabela, indicandoqual o papel (redator, visitante ou admin) que cada usurioexerce no sistema. possvel fazer isso usando o phpMyAdmin,
outra ferramenta grfica ou com os comandos SQL abaixo:
INSERTINTOusers (username,password,name,valid,ROLE)VALUES
('eminetto',md5('teste'),'Elton Minetto',1,'admin');
INSERTINTOusers (username,password,name,valid,ROLE)VALUES
('steve',md5('teste'),'Steve Jobs',1,'redator');
INSERTINTOusers (username,password,name,valid,ROLE)VALUES
('bill',md5('teste'),'Bill Gates',1,'visitante');
https://gist.github.com/987391
Podemos assim fazer testes e verificar que o acesso aos mtodos controlado de maneira muito rpida e fcil. O uso de ACLspermite um controle fcil de ser desenvolvido e com grandeversatilidade.
https://gist.github.com/987391https://gist.github.com/987391https://gist.github.com/1449759https://gist.github.com/987391https://gist.github.com/987391https://gist.github.com/987391https://gist.github.com/987391https://gist.github.com/987391https://gist.github.com/987391https://gist.github.com/1449759https://gist.github.com/1449759https://gist.github.com/1449759https://gist.github.com/1449759https://gist.github.com/1449759https://gist.github.com/14497595/27/2018 Zend Gramework
47/67
Navegao
O Zend Framework fornece um componente para facilitar a
criaode menus, o Zend_Navigation.Podemos usar o Zend_Navigation para gerar facilmente menus etens de navegao.
Exemplo:
No bootstrap adicionar:
/**
* inicializa a navegao
*
* @return void* @author Elton Minetto
**/
public function _initNavigation()
{
/* * navegacao */ $container = new Zend_Navigation(array( array( 'label' => 'Home', 'controller' => 'post', 'action' => 'retrieve', ), array( 'label' => 'Adicionar Post', 'controller' => 'post', 'action' => 'create', ), array( 'label' => 'Sair', 'controller' => 'auth', 'action' => 'logout', ), )); Zend_Registry::set('Zend_Navigation', $container);}
https://gist.github.com/1449791
No layout (ou em alguma view) basta adicionar a seguinte linha:
https://gist.github.com/1449791https://gist.github.com/1449791https://gist.github.com/1449791https://gist.github.com/1449791https://gist.github.com/1449791https://gist.github.com/1449791https://gist.github.com/1449791https://gist.github.com/14497915/27/2018 Zend Gramework
48/67
Podemos tambm integrar o Zend_Navigation com o Zend_Acl,para que o menu de opes seja renderizado de acordo com as
permisses do usurio. Para isso vamos reescrever as linhas queadicionamos agora a pouco no Bootstrap (OBS: preciso verificarse elas esto aps a criao do Zend_Acl):
/**
* inicializa a navegao
*
* @return void
* @author Elton Minetto
**/
public function _initNavigation(){
/* * navegacao */ $container = new Zend_Navigation(array( array( 'label' => 'Home', 'controller' => 'post', 'action' => 'retrieve', 'resource' => 'post', 'privilege' => 'retrieve' ), array( 'label' => 'Adicionar Post', 'controller' => 'post', 'action' => 'create', 'resource' => 'post', 'privilege' => 'create' ), array( 'label' => 'Sair', 'controller' => 'auth', 'action' => 'logout', 'resource' => 'auth', 'privilege' => 'logout' ), )); Zend_Registry::set('Zend_Navigation', $container);}
5/27/2018 Zend Gramework
49/67
https://gist.github.com/1449909
E no final do metodo init() do Blog_Controller_Action:
Zend_Layout::getMvcInstance()
->getView() ->navigation() ->setAcl($acl) ->setRole($role);
O Zend_Acl vai conversar com o Zend_Navigation e decidir
quais opes do menu devem aparecer, dependendo da role dousurio.Esta uma das coisas legais do Zend Framework. Apesar de serformado por uma srie de componentes que podem ser usadosem separado, a maioria deles integra-se de uma maneira muitotil.
Paginao
Usando o componente Zend_Paginator facilita uma dasnecessidades mais comuns em aplicaes web, a paginao dedados.
O componente Zend_Paginator possibilita ao programadorconfigurar uma srie de opes afim de tornar a paginao maisintuitiva. Atualmente o Zend_Paginator nos permite paginar quatrotipos de dados:
Array DbSelect
DbTableSelect
Iterator
Vamos modificar nosso sistema de blog para que ele usepaginao na pgina inicial.
https://gist.github.com/1449909https://gist.github.com/1449909https://gist.github.com/1449909https://gist.github.com/1449909https://gist.github.com/1449909https://gist.github.com/1449909https://gist.github.com/14499095/27/2018 Zend Gramework
50/67
Primeiro vamos fazer uma alterao no mtodo retrieveAction() doPostController.php. Vamos comentar a linha:
$result=$posts->fetchAll();//pega todos os posts
e adicionar as seguintes:
//criando a paginaao
Zend_Paginator::setDefaultScrollingStyle('Sliding');
Zend_View_Helper_PaginationControl ::setDefaultViewPartial('partials/
paginator.phtml');
//manda o paginador usar os dados vindos do banco
$paginator=Zend_Paginator::factory($posts->fetchAll());
//pagina atual. Se nao vier nenhuma pagina, mostra a primeira
$currentPage=$this->_getParam('page',1);
//5 tens por pgina
$paginator->setCurrentPageNumber($currentPage)-
>setItemCountPerPage(5);
//manda para a view
$this->view->data=$paginator;
https://
gist.github.com/987415
Neste momento apresentado o conceito de partials. Partialsso trechos de cdigos de viso (html, js, css) que podem serreutilizados por diversas views. Neste exemplo criado o tem queir mostrar o nmero de pginas que o paginador gerou. Ele serreutilizado em todas as pginas que precisarem de paginao. Ocdigo do arquivo views/scripts/partials/paginator.phtml :
5/27/2018 Zend Gramework
51/67
5/27/2018 Zend Gramework
52/67
Cache
A tcnica de cache muito usada para melhorar a performance desites, sejam eles de grande trfego ou no.
Teoricamente quase tudo pode ser armazenado em cache:resultados de consultas, imagens, arquivos css, arquivos js,trechos de cdigo html, etc.
No Zend Framework o cache fornecido usando-se a classeZend_Cache. O cacheamento fornecido ao programador atravsde frontends, enquanto que o armazenamento em si feito com
classes de backends. Isso torna o processo flexvel no quesitoarmazenamento e fcil para a manipulao.
O frontend mais usado o Core, padro do Framework. Este podeser extendido para atender as necessidades do usurio, mas namaioria das vezes isso no necessrio.
Os principais backends disponveis so:
File: os dados do cache so armazenados em arquivos no
sistema operacional Sqlite: salvos em um banco de dados Sqlite
Memcached: os dados sero salvos no Memcached, umservidor especfico para cache, usado por grandesarquiteturas como o Facebook
Apc: usa o cache em memria fornecido pela extenso APC(Alternative PHP Cache) do PHP
Xcache: usa a extenso do PHP, Xcache para armazenar osdados em memria
ZendPlatform: usa a soluo proprietria da Zend paraarmazenar o cache
Vamos ver alguns exemplos de uso. O primeiro passo criarmosentradas no nosso arquivo de configuraes, no application.ini:
;cache
cache.compression = true
5/27/2018 Zend Gramework
53/67
cache.frontend.lifetime = 7200
cache.frontend.automatic_serialization = true
;adaptador: File, Memcached ; APC
cache.backend.adapter = File
;cache em memcached
;cache.backend.options.srv1.host = localhost
;cache.backend.options.srv1.port = 11211
;cache.backend.options.srv1.persistent = true
;cache em arquivo
cache.backend.options.cache_dir = "/tmp"
https://gist.github.com/1469557
Agora vamos adicionar as seguintes linhas ao Bootstrap.php:
/**
* Inicializa o cache
*
* @return void
* @author Elton Minetto
*/
public function _initCache()
{
$config = Zend_Registry::get('config')->cache; $frontendOptions = array( 'lifetime' => $config->frontend->lifetime, // tempo de vida
'automatic_serialization' => $config->frontend-
>automatic_serialization
); $backendOptions = $config->backend->options->toArray(); // criando uma instancia do cache $cache = Zend_Cache::factory('Core',//frontend $config->backend->adapter, //backend
$frontendOptions,
$backendOptions);
/* * Salva o cache no Registry para ser usado posteriormente
https://gist.github.com/1469557https://gist.github.com/1469557https://gist.github.com/1469557https://gist.github.com/1469557https://gist.github.com/1469557https://gist.github.com/1469557https://gist.github.com/1469557https://gist.github.com/1469557https://gist.github.com/14695575/27/2018 Zend Gramework
54/67
*/ Zend_Registry::set('cache',$cache); /* * cache para metadados das tabelas
*/ Zend_Db_Table_Abstract::setDefaultMetadataCache($cache);}
https://gist.github.com/1469560
Agora vamos alterar o retrieveAction do PostController.php parausar o cache.
Onde havia estas linhas://busca os posts
$posts=newApplication_Model_Posts;
$this->view->data=$posts->fetchAll();
Vamos substitu-las por:
$cache=Zend_Registry::get('cache');
//busca os posts$posts=newApplication_Model_Posts;//cria um novo objeto Posts
//verifica se j est no cache o resultado
if(!$result=$cache->load('cachePosts')){
//no existe no cache, processar e salvar $result=$posts->fetchAll();//pega todos os posts $cache->save($result,'cachePosts');}
$this->view->data=$result;
https://gist.github.com/1469573
Desta forma a consulta no ser realizada novamente enquanto ocache no expire. No exemplo est configurado para durar 2horas (configurado no application.ini). Podemos indicar tambm otempo de vida de um tem em especfico (em segundos):
$cache->save($result,'cachePosts',array(),60);//1 min
http://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/arrayhttps://gist.github.com/1469573https://gist.github.com/1469573https://gist.github.com/1469573https://gist.github.com/1469573https://gist.github.com/1469573https://gist.github.com/1469573https://gist.github.com/1469560https://gist.github.com/1469560https://gist.github.com/1469560https://gist.github.com/1469560https://gist.github.com/1469560https://gist.github.com/14695605/27/2018 Zend Gramework
55/67
O terceiro parmetro, o array(), usado para atribuir uma tag paraa varivel do cache. Tags servem para agruparmos os tens docache, assim fica mais fcil manipularmos conjuntos de tens.
A qualquer momento podemos remover um tem do cache:$result=$cache->remove('cachePosts');
Ou remover todos os tens do cache:
// limpa todos os registros
$cache->clean(Zend_Cache::CLEANING_MODE_ALL);
// limpa somente os que esto vencidos
$cache->clean(Zend_Cache::CLEANING_MODE_OLD);
Tambm podemos usar o recurso de Cache para acelerar arenderizao de formulrios. Usar o Zend_Form para gerarformulrios aumenta a produtividade do desenvolvimento, masseu desempenho pode deixar a desejar quando comparado comformulrios gerados a moda antiga, direto em HTML. Usando-secache podemos melhorar isso.
Exemplo:
$cache = Zend_Registry::get('cache');if(!$form = $cache->load('Application_Form_Login')) {
$form = new Application_Form_Login; //salva o form renderizado no cache $cache->save($form->render(), 'Application_Form_Login');}
$this->view->form = $form;
https://
gist.github.com/1469589
Outros usos do Zend_Cache:
/*
* cache para metadados das tabelas. Usado pelos Models para salvaros detalhes da tabela (campos,chaves)
*/
Zend_Db_Table_Abstract::setDefaultMetadataCache($cache);
/*
https://gist.github.com/1469589https://gist.github.com/1469589https://gist.github.com/1469589https://gist.github.com/1469589https://gist.github.com/1469589https://gist.github.com/1469589https://gist.github.com/1469589https://gist.github.com/1469589https://gist.github.com/1469589https://gist.github.com/1469589https://gist.github.com/1469589https://gist.github.com/1469589https://gist.github.com/14695895/27/2018 Zend Gramework
56/67
* Configura o cache para a traducao*/Zend_Translate::setCache($cache);
/* coloca o zend_date e o zend_locale em cache */
Zend_Locale::setCache($cache);
Zend_Date::setOptions(array('cache'=>$cache));
https://gist.github.com/987409
Tambm possvel usar o Zend_Cache para armazenar assesses, algo til quando usado para salvar as sesses de
usurios, se usado com Memcached por exemplo (salvar sessesem cache usando o Backend File no muita vantagem, mas comMemcached ou APC muito mais rpido). Assim possvel usarvrios servidores para guardar a informao e ela ficaindependente do servidor Web (no caso do Memcached). Parai s s o p r e c i s o i m p l e m e n t a r a i n t e r f a c eZend_Session_SaveHandler_Interface, conforme o exemploabaixo:
5/27/2018 Zend Gramework
57/67
} } public function write($id, $sessionData) { $this->cache->save($sessionData, $id, array(), $this->maxlifetime); return true; } public function destroy($id) { $this->cache->remove($id); return true; } public function gc($notusedformemcache) { return true; }}
https://gist.github.com/1469654
Aps salvar contedo acima no arquivo library/Blog/Session/
Handler.php necessrio configurar o handler da sesso, nobootstrap, antes da inicializao da sesso :
Zend_Session::setSaveHandler(newBlog_Session_Handler($cache));
Tradues
Nos exemplos anteriores vimos a utilizao dos validadores do
Zend Framework para verificar se os campos obrigatrios de umformulrio foram digitados ou se possuam valores corretos. Masas mensagens de erro e validao so apresentadas por padrona lngua inglesa. Para facilitar o uso das mensagens em outraslnguas vamos usar o componente Zend_Translate.Para fazer uso do componente vamos inicialmente criar umdiretrio no projeto onde iremos armazenar os arquivos dastradues. Vamos chamar este diretrio de application/languages.Vamos adicionar as linhas abaixo no application.ini:
resources.locale.default = "pt_BR"
https://gist.github.com/1469654https://gist.github.com/1469654https://gist.github.com/1469654https://gist.github.com/1469654https://gist.github.com/1469654https://gist.github.com/1469654https://gist.github.com/1469654https://gist.github.com/14696545/27/2018 Zend Gramework
58/67
resources.translate.adapter = "csv"
resources.translate.data = APPLICATION_PATH "/languages"
E no Bootstrap.php vamos criar o mtodo _initTranslate:/**
* Inicializa o translate
*
* @return void
* @author Elton Minetto
*/
public function _initTranslate()
{
$config = Zend_Registry::get('config'); $translate = $config->resources->translate; $locale = $config->resources->locale; $zend_translate = new Zend_Translate($translate->adapter,$translate->data, $locale->default);
Zend_Registry::set('Zend_Translate', $zend_translate);}
Nas linhas acima criamos um objeto Zend_Translate, indicandoque o formato do arquivo CSV e a linguagem padro a pt_BR(portugus Brasil). Outros formatos so permitidos: Array, ini,gettext, tbx, etc.O objeto tambm registrado pelo Bootstrap usando oZend_Registry, facilitando sua utilizao no restante do projeto.
O arquivo de tradues inicial ficou da seguinte forma:
isEmpty;O campo deve ser preenchido
stringLengthTooShort;O valor do campo deve ter no minimo %min%
caracteres
stringLengthTooLong;O valor do campo deve ter no mximo %max%caracteres
notSame;Os valores fornecidos so diferentes
missingToken;Nenhuma senha foi fornecida
emailAddressInvalid;Endereo de e-mail invlido
hostnameInvalidHostname;Endereo invlido
notDigits;Valor invlido
hostnameUnknownTld;'%value%' um domnio desconhecido
hostnameLocalNameNotAllowed;'%value%' um domnio no permitido
emailAddressInvalidHostname;'%value%' no um email invlido
emailAddressInvalidFormat;'%value%' no um email invlido
dateInvalid;Data invlida
5/27/2018 Zend Gramework
59/67
https://gist.github.com/987413
O formato do arquivo : chave;Traduo.
Mais informaes sobre as mensagens de validao podem serencontradas neste link:
http://framework.zend.com/manual/en/zend.validate.messages.html
Tambm podemos usar o Zend_Translate para internacionalizartodas as mensagens do sistema. Por exemplo, na viso views/
scritps/post/create.phtml usamos o seguinte cdigo:
Caso precisemos alterar o sistema para ingls (mudando oparmetro pt_BR para en_US no application.ini), o framework irprocurar no arquivo application/languages/en_US.csv a linha:
Novo Post;New post
Caso esta linha no exista o texto Novo Post ser apresentado,caso contrrio ir apresentar o texto New post.Usando o Zend_Translate muito fcil criar aplicativos paramltiplas lnguas.
Enviando e-mails
Enviar e-mails uma funo recorrente em diversos tipos deaplicao Web. Neste tpico apresentado um controlador comalguns exemplos de como enviar e-mails usando o componenteZend_Mail.
5/27/2018 Zend Gramework
60/67
private$conta='[email protected]'; private$senha='senha'; private$de='[email protected]'; private$para='[email protected]';
//envio de e-mail texto publicfunctionindexAction(){
$assunto="Teste de envio de email ";
$mensagem="Isso apenas um teste de envioutilizando o Zend_Mail().";
try { $config=array( 'auth'=>'login', 'username'=>$this->conta, 'password'=>$this->senha, 'ssl'=>'ssl', 'port'=>'465' ); $mailTransport=newZend_Mail_Transport_Smtp($this->smtp,$config);
$mail=newZend_Mail('UTF-8'); $mail->setFrom($this->de); $mail->addTo($this->para); $mail->setBodyText($mensagem); $mail->setSubject($assunto); $mail->send($mailTransport); echo"Email enviado com SUCESSSO!"; }catch (Exception $e){ echo($e->getMessage()); } exit; }
//envio de e-mail html
publicfunctionhtmlAction(){ $assunto="Teste de envio de email em
HTML"; $mensagem="Isso apenas um teste de envioutilizando o
Zend_Mail().
At mais,
Elton
Minetto
Coderockr";
try { $config=array(
'auth'=>'login', 'username'=>$this->conta,
http://www.php.net/arraymailto:[email protected]:[email protected]:[email protected]:[email protected]:[email protected]:[email protected]:[email protected]:[email protected]:[email protected]:[email protected]://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/exithttp://www.php.net/exithttp://www.php.net/arrayhttp://www.php.net/arraymailto:[email protected]:[email protected]:[email protected]:[email protected]:[email protected]:[email protected]5/27/2018 Zend Gramework
61/67
'password'=>$this->senha, 'ssl'=>'ssl', 'port'=>'465' );
$mailTransport=newZend_Mail_Transport_Smtp($this->smtp,$config);
$mail=newZend_Mail('UTF-8'); $mail->setFrom($this->de); $mail->addTo($this->para); $mail->setBodyHtml($mensagem); $mail->setSubject($assunto); $mail->send($mailTransport); echo"Email enviado com SUCESSSO!"; }catch (Exception $e){ echo($e->getMessage()); } exit; }
//envio de e-mail com anexo
publicfunctionanexoAction(){ /** * verifica se o formulrio foi enviado */ if($_POST){ /** * Recebe os campos do formulrio */ $arqTmp=$_FILES["file"]["tmp_name"]; $arqName=$_FILES["file"]["name"]; $arqType=$_FILES["file"]["type"];
$assunto="Teste de envio de email com
Anexo"; $mensagem="Isso apenas um teste de envioutilizando o
Zend_Mail().
At mais,
Elton
Minetto
Coderockr";
try { $config=array( 'auth'=>'login', 'username'=>$this->conta, 'password'=>$this->senha,
'ssl'=>'ssl', 'port'=>'465'
http://www.php.net/arrayhttp://www.php.net/arrayhttp://www.php.net/exithttp://www.php.net/exit5/27/2018 Zend Gramework
62/67
); $mailTransport=newZend_Mail_Transport_Smtp($this->smtp,$config);
$mail=newZend_Mail('UTF-8'); $mail->setFrom($this->de); $mail->addTo($this->para); $mail->setBodyHtml($mensagem); $mail->setSubject($assunto); $mail->createAttachment(file_get_contents($arqTmp),$arqType,
Zend_Mime::DISPOSITION_INLINE,Zend_Mime::ENCODING_BASE64,$arqName);
$mail->send($mailTransport); echo"Email enviado com SUCESSSO!"; }catch (Exception $e){ echo($e->getMessage()); } }
}
}
https://gist.github.com/987420
Foi criada uma viso para mostrar o formulrio de envio doarquivo.
views/scripts/email/anexo.phtml:
Arquivo:
https://gist.github.com/987421
Com algumas alteraes no exemplo acima possvel adapt-loao seu projeto
http://www.php.net/file_get_contentshttp://www.php.net/file_get_contentshttps://gist.github.com/987421https://gist.github.com/987421https://gist.github.com/987421https://gist.github.com/987421https://gist.github.com/987421https://gist.github.com/987421https://gist.github.com/987420https://gist.github.com/987420https://gist.github.com/987420https://gist.github.com/987420https://gist.github.com/987420https://gist.github.com/9874205/27/2018 Zend Gramework
63/67
Diagnstico da aplicao
O Zend Framework fornece algumas ferramentas para facilitar alocalizao de bugs e erros nos sistemas desenvolvidos.
Uma destas ferramentas o Zend_Debug. O seu funcionamento simples:
Zend_Debug::dump($var);
Zend_log
Outra ferramenta o Zend_Log. Com ele possvel realizar logsem diversos backends, tais como arquivos e bancos de dados.
Vamos criar um log em nosso bootstrap para podermos usar emqualquer parte do projeto:
/**
* inicializa o log
** @return void
* @author Elton Minetto
**/
public function _initLog()
{
$writer = new Zend_Log_Writer_Stream('/tmp/zf_log.txt'); $log = new Zend_Log($writer); Zend_Registry::set('log', $log);}
Agora podemos gerar logs nos nossos controllers ou models,usando:
$log=Zend_Registry::get(log);
$log->log(Mensagem a ser salva,Zend_Log::INFO);
O segundo parmetro da funo log() a prioridade da
mensagem. As opes disponveis so:
http://www.php.net/loghttp://www.php.net/loghttp://www.php.net/loghttp://www.php.net/loghttp://www.php.net/log5/27/2018 Zend Gramework
64/67
Nome Uso
Zend_Log::EMERG
Emergncia:sistemanopodeserusado
Zend_Log::ALERT
Alerta:aodevesertomada
Zend_Log::CRIT
Crtico
Zend_Log::ERR
Erro
Zend_Log::WARN
Aviso
Zend_Log::NOTICE
Observaes
Zend_Log::INFO
Informativo
Zend_Log::DE
BUG
Mensagens
dedebug
Para cada prioridade existe um mtodo especfico do objetoZend_Log. Ento as duas linhas abaixo tem a mesma funo:
$log->log(Erro crtico,Zend_Log::CRIT);
$log->crit(Erro crtico)
Alm de salvar o log em arquivos podemos usar outros formatoscomo o Zend_Log_Writer_Db (salva em bancos de dados) e o
http://www.php.net/loghttp://www.php.net/log5/27/2018 Zend Gramework
65/67
Zend_Log_Writer_Firebug( envia a mensagem para ser mostradapelo Firebug/FirePHP). No exemplo abaixo criamos o log usandoo banco SQLite e arquivos:
/**
* inicializa o log
*
* @return void
* @author Elton Minetto
**/
public function _initLog()
{
$writer = new Zend_Log_Writer_Stream('/tmp/zf_log.txt'); $db = Zend_Db::factory("pdo_sqlite", array('dbname'=>'/tmp/zf_log.db'));
$columnMapping = array('pri' => 'priority', 'msg' =>'message');
$dbWriter = new Zend_Log_Writer_Db($db, 'log', $columnMapping);
$log = new Zend_Log(); $log->addWriter($writer); $log->addWriter($dbWriter); Zend_Registry::set('log', $log);}
necessrio criar o banco de dados caso este no exista:
sqlite3 zf_log.db
create table log(pri int, msg text);
Zend_Db_Profiler
O Zend Framework possui um componente chamadoZend_Db_Profiler que nos permite realizar o profiling dos acessosao banco que pode ser utilizado em conjunto com o componenteZend_Db_Profiler_Firebug.
Primeiramente, preciso ter os complementos do Firefox Firebug(https://addons.mozilla.org/pt-BR/firefox/addon/1843) e FirePHP(http://www.firephp.org/) instalados, ou seja, s possvel usareste recurso com o Firefox (no fiz testes com as verses doFirebug para Chrome, ento no sei como essa feature secomporta neste navegador).
http://www.firephp.org/https://addons.mozilla.org/pt-BR/firefox/addon/1843http://www.firephp.org/http://www.firephp.org/https://addons.mozilla.org/pt-BR/firefox/addon/1843https://addons.mozilla.org/pt-BR/firefox/addon/18435/27/2018 Zend Gramework
66/67
preciso tambm adicionar as linhas abaixo no Bootstrap, nomtodo _initDb():
/**
* Inicializa o banco de dados. Somente necessrio se desejado salvar
a conexo no Registry*
* @return void
* @author Elton Minetto
*/
public function _initDb()
{
$db = $this->getPluginResource('db')->getDbAdapter(); // Configuring Profiler
$profiler = new Zend_Db_Profiler_Firebug('db-profiling');
$profiler->setEnabled(true);$db->setProfiler($profiler);
Zend_Db_Table::setDefaultAdapter($db); Zend_Registry::set('db', $db);}
O resultado pode ser visto na imagem abaixo
5/27/2018 Zend Gramework
67/67
Todas as consultas SQL que foram geradas pela pgina correnteso apresentadas no console do Firebug. Com isso fcil verificarquais consultas esto sendo executadas, quanto tempodemoraram e quantas linhas foram retornadas. Essas informaes
so de extrema utilidade para realizar uma melhoria deperformance das pginas baseadas em resultados vindos debancos de dados.
Concluso
Certamente no consegui aqui englobar todas as funcionalidades
do Zend Framework, mas esse no era exatamente o objetivodeste livro. A idia aqui era apresentar as principais caractersticase como us-las em uma aplicao comum e espero ter atingidoesse modesto objetivo.Uma das vantagens de ser um e-book que esse livro pode servivo, coisa que mais difcil para um livro impresso. Todos ostrechos de cdigos do PDF possuem links para uma versoonline, o que facilita a cpia para o seu editor de programaofavorito, mas que principalmente facilita alguma possvel correo
que venha a acontecer. Ento acompanhe o site oficial deste livro,o http://www.zfnapratica.com.br para acompanhar qualquermelhoria ou correo nos cdigos ou textos. E caso tenha algumasugesto ficaria feliz em receb-la e publicar no site. Meus dadosde contato esto na introduo deste livro. isso. Happy coding para voc!
http://www.zfnapratica.com.br/http://www.zfnapratica.com.br/http://www.zfnapratica.com.br/