Criando um CRUD com Zend Framework 2 e Doctrine 2

Veja nesse artigo como criar um projeto CRUD utilizando dois dos principais frameworks utilizados atualmente: Zend e Doctrine.

Neste artigo veremos como criar um projeto CRUD utilizando dois dos principais frameworks utilizados atualmente: Zend Framework e Doctrine. Mas antes de iniciar o processo de construção do projeto, vamos definir quais as ferramentas utilizadas para o projeto, além do servidor utilizado para o projeto, que será o XAMPP e a IDE escolhida é o NETBEANS.

Primeiramente devemos entrar no site do Zend Framework e realizar o download do mesmo, além do exemplo Skeleton, que está disponível no próprio site. O Skeleton é um projeto inicial que utiliza o Zend Framework como base. Baixe o Skeleton da através do link http://framework.zend.com/downloads/skeleton-app.

Após o download, adicione no servidor e rode o projeto, assim, logo vê-se que já existe uma estrutura básica, conhecida como Application, que conta com um projeto simples do Zend, ao qual a partir deste iniciaremos a construção dos demais.

Veja na Figura 1 de como o projeto deve estar caso a instalação do skeleton tenha sido feita corretamente.

Figura 1. Projeto inicial do Zend Framework 2

Com o projeto configurado corretamente, iniciamos o projeto de modificação para a inclusão do Doctrine. Primeiro, abra o arquivo composer.json da raiz do projeto e altere este arquivo adicionando a dependência do Doctrine2, como mostra a Listagem 1 e execute o composer para atualizar as libs do seu projeto.

Listagem 1. Arquivo composer.json completo do projeto.

{ "name": "zendframework/skeleton-application", "description": "Skeleton Application for ZF2", "license": "BSD-3-Clause", "keywords": [ "framework", "zf2" ], "homepage": "http://framework.zend.com/", "require": { "php": ">=5.3.3", "zendframework/zendframework": "2.3.*", "doctrine/doctrine-orm-module" : "0.*" } }

Após as libs atualizadas iremos iniciar a configuração do projeto para aceitar o Doctrine 2, para isto, abra o arquivo application.config.php, conforme a Figura 2, e adicione quais os módulos serão carregados pelo projeto.

Figura 2. Caminho para chegar ate o arquivo application.config.php

Neste arquivo adicione as linhas DoctrineModule e DoctrineORMModule, conforme mostra a Listagem 2. Além disso, é necessário criar dentro da pasta data as pastas DoctrineORMModule e DoctrineORMModule/Proxy.

Listagem 2. Arquivo application.config.php com a alteração do modulo

'modules' => array( 'Application', 'DoctrineModule', 'DoctrineORMModule' ),

Após adicionar os módulos e criar as pastas necessárias para o funcionamento do Doctrine, vamos iniciar a construção do projeto e, para isto, altere o arquivo responsável por mostrar a primeira página do nosso projeto. Todos os arquivos de tela (layout) ficam armazenados dentro da pasta Application/view.

Abra o arquivo Application/view/application/index/index.phtml e crie a página inicial da aplicação. No arquivo índex.phtml iremos criar um simples formulário, conforme mostra a Listagem 3, para inserir funcionários no projeto.

Listagem 3 – Formulário php para adicionar funcionario

<h3>Adicionar Funcionário</h3> <form method="post"> Informe o nome do funcionário..: <br> <input type="text" name="nome"> <br><br> Informe o cpf do funcionário..: <br> <input type="text" name="cpf"> <br><br> Informe o salário do funcionário..: <br> <input type="text" name="salario"> <br><br> <input type="submit" value="Adicionar"> </form> <br><br> <?php echo $this->resp; ?>

A linha $this->resp será utilizada posteriormente para enviar mensagens do controle para as nossas páginas, mas neste momento ela não vai imprimir nenhum valor. Se executar o nosso projeto já podemos observar o mesmo sendo construído, conforme a Figura 3.

Figura 3. Página inicial do sistema

Após o usuário preencher os dados deste formulário e clicar no botão Adicionar, o Zend Framework irá chamar a mesma URL, visto que não adicionamos nenhuma action para o nosso form. Com isso, a classe IndexController.php será chamada novamente e seu método actionIndex() carregado mais uma vez. É justamente neste método onde temos que preparar a gravação no banco de dados.

Vá ate o arquivo Application/src/Application/Controller/IndexController.php e modifique o mesmo conforme a Listagem 4.

Listagem 4. Código do IndexController.php recebendo os dados do formulário

public function indexAction() { $request = $this->getRequest(); $result = array(); if($request->isPost()) { $nome = $request->getPost("nome"); $cpf = $request->getPost("cpf"); $salario = $request->getPost("salario"); $result["resp"] = $nome. ", enviado corretamente!"; } return new ViewModel($result); }

Após a criação do método indexAction(), o projeto já está recebendo os dados dos três campos do formulário: nome, CPF e salário, e retornando para a index.phtml através da variável $result[“resp”] e a mensagem $nome enviada corretamente.

Neste momento vamos criar a classe de entidade responsável pela ligação dos dados do formulário com o banco de dados, para isso, crie uma pasta Model dentro de Application/src/Application e uma classe Funcionario.php dentro da pasta Model.

A classe Funcionario.php irá conter os atributos do formulário, o encapsulamento com set e get destes atributos e um mapeamento do doctrine referenciando a tabela funcionário do banco de dados. Veja na Listagem 5 como é a classe Funcionario.php

Listagem 5 – Classe Funcionario.php com o mapeamento do Doctrine 2.

<?php namespace Application\Model; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity */ class Funcionario { /** * @ORM\Id * @ORM\GeneratedValue("AUTO") * @ORM\Column(type="integer") */ private $id; /** * @ORM\Column(type="string", length=50) */ private $nome; /** * @ORM\Column(type="string", length=15) */ private $cpf; /** * @ORM\Column(type="decimal") */ private $salario; public function getId() { return $this->id; } public function setId($id) { $this->id = $id; } public function getNome() { return $this->nome; } public function setNome($nome) { $this->nome = $nome; } public function getCpf() { return $this->cpf; } public function setCpf($cpf) { $this->cpf = $cpf; } public function getSalario() { return $this->salario; } public function setSalario($salario) { $this->salario = $salario; } }

Podemos ver já o mapeamento do doctrine para cada um dos atributos e podemos observar a utilização do Doctrine\ORM\Mapping, pois o mesmo é utilizado para carregar as classes de mapeamento do Doctrine.

O elemento Id é utilizado para definir a chave primária da classe e o elemento GeneratedValue é adicionado para definir o tipo de value para este campo, no caso campo auto incremento, e por fim, o atributo Column define o tipo do campo, a quantidade de caracteres, entre outros parâmetros referentes a coluna.

Com a classe Funcionario devidamente mapeada, vamos criar o banco de dados conforme a Listagem 6.

Listagem 6. Código para a criação da tabela no banco de dados

create database devmedia_site; use devmedia_site; create table funcionario( id int auto_increment primary key, nome varchar(50), cpf varchar(15), salario double );

Vamos realizar a configuração do doctrine para o projeto agora: primeiro vamos criar um arquivo dentro da pasta config/autoload chamado de doctrine_orm.local.php, que é responsável pela configuração com o banco de dados e nele que iremos adicionar os valores para usuário, senha e nome do banco de dados utilizado, conforme a Listagem 7.

Listagem 7. Arquivo de configuração com o banco de dados pelo doctrine.

<?php return array( 'doctrine' => array( 'connection' => array( 'orm_default' => array( 'driverClass' => 'Doctrine\DBAL\Driver\PDOMySql\Driver', 'params' => array( 'host' => 'localhost', 'port' => '3306', 'user' => 'root', 'password' => '', 'dbname' => 'devmedia_site', ) ) ) ), );

Conforme a listagem acima, podemos ver os parâmetros para o caminho do banco de dados, a porta utilizada, usuário, senha e nome do banco de dados. Altere este arquivo conforme a configuração desejada. Depois desta vamos à configuração do módulo, pois é necessário definir parâmetros do doctrine. Para isso, vá até o arquivo Application/config/module.config.php e adicione os valores da Listagem 8.

Listagem 8. Configuração do doctrine para o modulo.

'doctrine' => array( 'driver' => array( // defines an annotation driver with two paths, and names it `my_annotation_driver` 'my_annotation_driver' => array( 'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver', 'cache' => 'array', 'paths' => array( __DIR__ . "/src/Application/Model" ), ), // default metadata driver, aggregates all other drivers into a single one. // Override `orm_default` only if you know what you're doing 'orm_default' => array( 'drivers' => array( // register `my_annotation_driver` for any entity under namespace `My\Namespace` 'Application\Model' => 'my_annotation_driver' ) ) ) )

Podemos ver que foi configurado o driver utilizado pelo projeto, a referência do path onde estão localizadas as classes mapeadas pelo doctrine conforme a linha 'paths' => array( __DIR__ . "/src/Application/Model"), que define para o doctrine procurar na pasta Model as classes que possuem anotação. Logo abaixo vemos a configuração do namespace utilizado nas classes de Model, conforme a linha 'Application\Model' => 'my_annotation_driver'.

Após esta configuração realizada corretamente, o próximo passo é executar o processo para iniciar o CRUD. Então, volte até a classe IndexController onde vamos terminar a gravação de dados que havia iniciado no método indexAction(), e crie uma instância da classe Funcionario, adicione os dados do formulário para este objeto, chame o serviço do Doctrine e realize a gravação dos dados, conforme a Listagem 9.

Listagem 9. Método indexAction() finalizado com a operação de gravar dados corretamente.

public function indexAction() { $request = $this->getRequest(); $result = array(); if($request->isPost()) { try{ $nome = $request->getPost("nome"); $cpf = $request->getPost("cpf"); $salario = $request->getPost("salario"); $funcionario = new \Application\Model\Funcionario(); $funcionario->setNome($nome); $funcionario->setCpf($cpf); $funcionario->setSalario($salario); $em = $this->getServiceLocator()->get("Doctrine\ORM\EntityManager"); $em->persist($funcionario); $em->flush(); $result["resp"] = $nome. ", enviado corretamente!"; } catch (Exception $e){ } } return new ViewModel($result); }

Conforme visto na listagem acima, após receber os dados do formulário e adicionar no objeto $funcionario, para utilizar o Doctrine basta chamar o serviço do Doctrine com $this->getServiceLocator()->get("Doctrine\ORM\EntityManager"), e depois dele já iniciado, utilize o método $em->persist($funcionario).

Este método faz com que o Doctrine olhe a classe Funcionario.php e conforme o que foi mapeado na classe, grava os dados nos campos e tabela correspondentes. Por fim, é necessário chamar o método $em->flush() que faz o commit das operações anteriores.

Após a finalização do cadastrar funcionário, vamos criar um link para a página de lista de funcionários. Adicione um link, conforme a Listagem 10, no arquivo index.phtml com referência para o controller listarAction() da mesma classe, IndexController que será criado posteriormente.

Listagem 10. Link adicionado na pagina index.phtml

<a href="<?php echo $this->url('application/default', array('controller' => 'index', 'action' => 'listar')); ?>">Listar Funcionario</a>

Crie um método listarAction() dentro da classe Application/src/Application/Controller/IndexController.php com a função de realizar a busca dos dados da tabela funcionário. Esta será uma busca simples, com um select de todos os dados da tabela funcionário. Para isto, basta chamar o serviço do Doctrine e utilizar o método findAll(), conforme a Listagem 11.

Listagem 11. Método listarAction() carregando os dados com doctrine do banco de dados

public function listarAction() { $em = $this->getServiceLocator()->get("Doctrine\ORM\EntityManager"); $lista = $em->getRepository("Application\Model\Funcionario")->findAll(); return new ViewModel(array('lista' => $lista)); }

Repare que o método listarAction() faz a consulta dos dados referente ao Repositório de Funcionário e seu resultado é enviado para uma variável lista no retorno do método. Agora deve-se criar um arquivo listar.phtml e mostrar a variável lista que possui os dados dos funcionários. O arquivo listar.phtml deve ser criado dentro do caminho Application/view/application/índex/listar.phtml, como mostra a Listagem 12.

Listagem 12. Página listar.phtml com a tabela dos dados do banco.

<h3>Listar Funcionário</h3> <table> <tr> <th>NOME</th> <th>CPF</th> <th>SALÁRIO</th> <th>EDITAR</th> <th>EXCLUIR</th> </tr> <?php foreach ($this->lista as $f): ?> <tr> <td><?php echo $f->getNome(); ?></td> <td><?php echo $f->getCpf(); ?></td> <td><?php echo $f->getSalario(); ?></td> <td>Editar</td> <td>Excluir</td> </tr> <?php endforeach; ?> </table> <a href="<?php echo $this->url('home'); ?>">Voltar</a>

Vamos criar uma tabela e mostrar os dados provenientes do método listarAction(), a listagem dos dados acontece através de um foreach simples da variável lista do controle. Para cada iteração realizada no foreach, o Zend cria um novo objeto $f referente a classe Funcionario e para imprimir os atributos de Funcionário é necessário utilizar os métodos get().

Para continuar com o projeto é necessário criar um nova rota que permita o envio de id (código) dos funcionários, para isto basta irmos no arquivo Application/config/module.config.php e adicionar a nova rota conforme mostra a Figura 4e a Listagem 13.

Figura 4.Parte do arquivo module.config.php com a nova rota

Listagem 13.Nova rota criada para o editar e o excluir

'rota2' => array( 'type' => 'Segment', 'options' => array( 'route' => '/application/flag/[:action]/[:id][/]', 'defaults' => array( '__NAMESPACE__' => 'Application\Controller', 'controller' => 'Index', ), ), ),

Podemos ver a criação de uma rota do tipo Segment, que permite dados cariados na URL. A mesma será executada sempre que na URL/application/flag/aparecer, uma action e um valor para o id. Com isso podemos ir no arquivo listar.phtml e adicionar as rotas para os links de editar e excluir, conforme a Listagem 14.

Listagem 14.Link para editar e excluir os dados

<td> <a href="<?php echo $this->url('rota2', array( 'action' => 'editar', 'id' => $f->getId() )); ?>"> Editar</a></td> <td> <a href="<?php echo $this->url('rota2', array( 'action' => 'excluir', 'id' => $f->getId() )); ?>"> Excluir</a></td>

Repare que após o comando $this->url() definimos o valor rota2 que havia sido criada anteriormente e apenas alteramos o valor do action e do id. Agora devemos criar o método editarAction() e excluirAction() dentro do controller IndexController, e o método excluirAction() será redirecionado para a Listagem 15. Já o método editarAction() terá uma página para realizar a edição dos dados.

Listagem 15.Método para editar e excluir o funcionário

public function excluirAction() { $id = $this->params()->fromRoute("id", 0); $em = $this->getServiceLocator()->get("Doctrine\ORM\EntityManager"); $funcionario = $em->find("Application\Model\Funcionario", $id); $em->remove($funcionario); $em->flush(); return $this->redirect()->toRoute('application/default', array('controller' => 'index', 'action' => 'listar')); } public function editarAction() { $id = $this->params()->fromRoute("id", 0); $em = $this->getServiceLocator()->get("Doctrine\ORM\EntityManager"); $funcionario = $em->find("Application\Model\Funcionario", $id); return new ViewModel(array('f' => $funcionario)); }

Conforme a listagem acima, vemos que através de $this->params()->fromRoute("id", 0) buscamos o id que foi adicionado na URL, e com este valor vamos no banco através do doctrine e buscamos o Funcionário correspondente com $em->find("Application\Model\Funcionario", $id).

Com o funcionário conhecido pelo seu id, no método excluir basta chamar a função remove() do doctrine para deletar este registro no banco de dados e redirecionar para a listagem novamente. Já no exemplo do editar iremos retornar o funcionário encontrado para o arquivo editar.phtml que deve ser criado em Application/view/application/índex/editar.phtml.

O arquivo editar.phtml deve ser criado igual a index.phtml, mas sua diferença é pelo fato dos inputs possuírem value para o valor do funcionário devolvido pelo método editarAction(). Veja na Listagem 16 como deve ser o formulário editar.

Listagem 16.Formulário para editar o funcionário

<h3>Editar Funcionário</h3> <form method="post"> Informe o nome do funcionário..: <br> <input type="text" name="nome" value="<?php echo $this->f->getNome(); ?>"> <br><br> Informe o cpf do funcionário..: <br> <input type="text" name="cpf" value="<?php echo $this->f->getCpf(); ?>"> <br><br> Informe o salário do funcionário..: <br> <input type="text" name="salario" value="<?php echo $this->f->getSalario(); ?>"> <br><br> <input type="submit" value="Editar"> </form> <br><br> <a href="<?php echo $this->url('application/default', array('controller' => 'index', 'action' => 'listar')); ?>">Listar Funcionario</a>

Após alterar os dados do formulário e clicar no botão EDITAR, o Zend chamará novamente o método editarAction(), porém os dados do formulário serão enviados, com estes valores podemos alterar o valor inicial adicionado no banco de dados, conforme a Listagem 17.

Listagem 17.Método editarAction() concluído.

public function editarAction() { $id = $this->params()->fromRoute("id", 0); $em = $this->getServiceLocator()->get("Doctrine\ORM\EntityManager"); $funcionario = $em->find("Application\Model\Funcionario", $id); $request = $this->getRequest(); if($request->isPost()) { try{ $nome = $request->getPost("nome"); $cpf = $request->getPost("cpf"); $salario = $request->getPost("salario"); $funcionario->setNome($nome); $funcionario->setCpf($cpf); $funcionario->setSalario($salario); $em = $this->getServiceLocator()->get("Doctrine\ORM\EntityManager"); $em->merge($funcionario); $em->flush(); } catch (Exception $e){ } return $this->redirect()->toRoute('application/default', array('controller' => 'index', 'action' => 'listar')); } return new ViewModel(array('f' => $funcionario)); }

Conforme a listagem acima, iremos receber os dados do formulário e basta chamar o método merge() do doctrine que os dados são modificados na tabela funcionário.

Com isto finalizamos nosso artigo sobre criação de um projeto utilizando Zend Framework 2 e Doctrine 2. Eespero que possa ter ajudado a todos vocês, obrigado a todos e bons estudos.

Links

https://netbeans.org/

https://www.apachefriends.org/pt_br/index.html

Ebook exclusivo
Dê um upgrade no início da sua jornada. Crie sua conta grátis e baixe o e-book

Artigos relacionados