Zend Gramework

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/987319
  • 5/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/987325
  • 5/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.html
  • 5/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/array
  • 5/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/1473182
  • 5/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/1455143
  • 5/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/987377
  • 5/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/1335245
  • 5/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/1335264
  • 5/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/1469916
  • 5/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/1449550
  • 5/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/1449567
  • 5/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/1449742
  • 5/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/1449759
  • 5/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/1449791
  • 5/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/1449909
  • 5/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/1469557
  • 5/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/1469560
  • 5/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/1469589
  • 5/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/1469654
  • 5/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/exit
  • 5/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/987420
  • 5/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/log
  • 5/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/log
  • 5/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/1843
  • 5/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/