[ Tutorial ] Zend Framework – Parte 06

Models, CRUD, Zend_Db_Table

Sumário

Na parte anterior aprendemos como criar Forms e enviar emails utilizando o Zend_Mail.
Vamos agora aprender a trabalhar com banco de dados e ver o conceito de Models dentro do Zend Framework utilizando o DbTable e as operações básicas com o paradigma CRUD.

Models

Basicamente, quando falamos de Models falamos de Banco de Dados ou uma coleção de Métodos dentro de uma Classe Model que permite agilizar processos relacionados a banco de dados.
O Model é manipulado pelo Controller e os dados retornados ficam disponíveis para você utilizar em qualquer lugar de sua aplicação.
Apesar de Model estar relacionado com banco de dados, na verdade, qualquer operação que modele dados pode ser considerado um model, como por exemplo, uma classe de Manipulação de Imagens.

CRUD

Com o sistema de Models do Zend é possível criar um sistema CRUD facilmente, pois ele possui métodos disponíveis através da classe Zend_Db_Table_Abstract. Para quem não conhece o significado de CRUD, o mesmo é um acrônimo para as quatro operações básicas em bancos de dados relacionais:

  • Create – Criar ou adicionar novas entradas
  • Read (Retrived) – Ler, recuperar ou ver entradas existentes
  • Update – Atualizar ou editar entradas existentes
  • Delete (Destroy) – Remover entradas existentes

Criando o Model

Para criar um Model basta digitar a linha de comando abaixo

 lang="plain
zf create model NOME_DO_MODEL

Isto criará o arquivo NOME_DO_MODEL.php dentro da pasta /application/models.

Mas para trabalhar com bancos de Dados e utilizar a class Zend_Db_Table_Abstract é preciso adicionar o parametro ‘db-table‘ ao invés de model:

 lang="plain
zf create db-table NOME_DO_MODEL NOME_TABElA_NO_BANCO

Isto criará uma pasta dentro de models chamada DbTable e dentro dela o arquivo NOME_DO_MODEL.php.

Vamos ver isto na prática criando o Model “Usuario” que vamos utilizar para criar nosso Sistema de Autenticação.

Digite a linha abaixo:

 lang="plain
zf create db-table Usuario usuarios

E acesse o arquivo gerado em /application/models/DbTable/Usuario.php.
Ele deve conter:


class Application_Model_DbTable_Usuario extends Zend_Db_Table_Abstract
{
    protected $_name = 'usuarios';
}

Como você pode ver o ZF Tool criou uma classe Application_Model_DbTable_Usuario que é estendida de Zend_Db_Table_Abstract e dentro da classe a propriedade $_name. Esta propriedade é o nome da tabela no banco de dados que passamos na linha de comando. Você pode alterar manualmente, caso precise futuramente. E também pode chamar $this->_name dentro dos métodos para trocar de tabela caso necessário.

Métodos CRUD

O Zend_Db_Table_Abstract é uma interface orientada a objetos para as tabelas do banco de dados. Ela oferece métodos para muitas operações comuns em tabelas. A classe é extensível, por isto fica fácil modificar e adaptar conforme nossas necessidades.

Esta interface foi desenvolvida como implementação do Padrão de Projeto “Table Data Gateway” e também inclui uma classe que implementa o Padrão “Row Data Gateway”.

Os métodos mais comuns são:

  • insert()
  • update()
  • delete()
  • find()
  • fetchAll()
  • fetchRow()

Nós poderíamos utilizar diretamente estes métodos ou inventar moda e criar métodos do tipo:

  • getUsuario()
  • addUsuario
  • updateUsuario
  • deleteUsuario

Mas para mantermos as coisas no lugar, vamos utilizar diretamente os métodos da interface.

Conexão Com o Banco de Dados

Pois é! Antes de mais nada precisamos informar ao Zend como se conectar ao banco de dados.
Isto é algo fácil, relativamente.
Para configurar uma conexão utilizaremos o nosso arquivo de configuração application.ini.
Abra o arquivo e na seção [production] insira as linhas:

 lang="plain
[production]
resources.db.adapter = "Pdo_Mysql"
resources.db.params.host = "localhost"
resources.db.params.username = "root"
resources.db.params.password = ""
resources.db.params.dbname = "tutorial-zend"
resources.db.params.charset = utf8

NOTA Creio que não preciso dizer para você colocar as suas configurações ai!

As linhas acima são bem intuitivas, mas a mais interessante é a primeira onde informamos ao Zend que vamos utilizar o PDO. Nesta linha está o poder da abstração. Se amanhã ou depois você quiser trocar de banco de dados, basta modificar o valor de resources.db.adapter e você não precisará fazer mais nada, caso você tenha utilizado somente as interfaces do Zend para manipulação de banco de dados.

Utilizando o Zend Tools para configurar a Conexão Adicionado: 25/06/13

Você também poderia utilizar o ZF para configurar a conexão com o banco de dados.
Para tal, considerando as configurações anteriores que você colocou no application.ini, você deverá acessar o diretório onde você criou o projeto com o ZF e digitar a linha de comando:


zf configure db-adapter "adapter=Pdo_Mysql&host=localhost&username=root&password=&dbname=tutorial-zend&charset=utf8"

Ao executar o comando acima, o código gerará todos os parametros de configuração que definimos manualmente antes.
Note que todos os parametros de configuração são passados como se fosse um URL separado por &CHAVE=VALOR.

Tabela de Usuários

Antes de prosseguirmos com os experimentos, vamos criar a tabela que o zend irá se comunicar para realizar as operações CRUD que vamos aprender logo abaixo.

Eu utilizei o MySQL, mas se você tem experiencia com outro banco de dados, sinta-se à vontade para utilizar o mesmo. Apenas não modifique os nomes dos campos ainda, para que não haja incompatibilidades com os passos do tutorial.

 lang="plain
CREATE TABLE IF NOT EXISTS `usuarios` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `nome` varchar(120) COLLATE utf8_unicode_ci NOT NULL,
  `email` varchar(120) NOT NULL,
  `login` varchar(120) NOT NULL,
  `senha` varchar(30) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

IMPORTANTE: A tabela acima é simples justamente para facilitar no aprendizado e não tomar tempo desnecessário.

Método insert()

Para inserir um novo registro utilizamos o método insert() juntamente com um array contendo os campos da tabela e os valores a serem registrados.

Administração de Usuários

Vamos então criar agora um controller dentro do módulo admin a fim de manipularmos os usuários de nossa aplicação.

Abra o Prompt de Comando do DOS ou o Terminal, acesse a pasta do projeto e digite:

 lang="plain
zf create controller usuario 1 admin

Esta linha de comando irá gerar os arquivos do Controller e View para UsuarioController.
Vale a pena notar que o nome da classe apareceu agora prefixado com ‘Admin_’ e para acessar o nosso controller temos que utilizar ‘admin’ ao invés de ‘default’.


class Admin_UsuarioController extends Zend_Controller_Action
{

    public function init()
    {
        /* Initialize action controller here */
    }

    public function indexAction()
    {
        // action body
    }
}

Você pode testar acessando: http://zend.localhost/admin/usuario. Neste caso, o action será ‘index‘ e o controller ‘usuario‘.

Note que o layout carregado é o mesmo do módulo default.

Por ora deixe como está, mais adiante veremos como trocar de layout.

Feito isto, vamos informar ao zend que queremos utilizar nosso Model. Para tal, dentro do método init() do Controller Usuario, vamos criar um objeto a partir de nossa classe Model.


...
    public function init()
    {
        // Não preciso explicar não eh?
        $this->_db = new Application_Model_DbTable_Usuario();
    }
...

E para testar, vamos criar um action dentro do controller Usuario do módulo Admin.

 lang="plain
zf create action add usuario 1 admin

Creio que você já sabe o que a linha acima significa!

Feito isto, vamos criar o código para controlar a criação de um novo usuário.


...
    public function addAction()
    {
        $dados = array(
	        'id' => null,
	        'nome' => 'Zé Ninguém',
	        'email' => 'zeninguem@teste.com',
	        'login' => 'zeninguem',
	        'senha' => md5('123456'),
        );
        $res = $this->_db->insert( $dados );
    }
...

Fácil, né? Pois é, nós criamos um array e passamos ele como valor para o método insert().
Note que foi utilizado o tipo null para o campo ‘id’.
Isto precisa ser feito assim para que o método insert() retorne o último ID inserido CASO você precise.
Como estamos utilizando uma interface, o Zend já se encarregou de fazer a conexão com o banco de dados que configuramos no arquivo de configuração. Para que a conexão aconteça, basta chamar o Model desejado. Por isto que criamos a propriedade $_db em nossa classe controladora de usuários, para deixar a conexão disponível em todo o controller.

Acesse agora a página do action que criamos para processar o código que criamos para inserir um novo usuário.

O URL ficou assim: http://zend.localhost/admin/usuario/add

Verifique no banco de dados que foi inserido um registro contendo as informações passadas no vetor acima.

O Método update()

Se você gostaria de atualizar alguma informação, você utilizará o método update(). Este método também precisará de um array contendo os campos e valores.

Este método espera que você passe um ID e como estamos trabalhando com CRUD que normalmente somente atualiza um registro por vez, há uma limitação para este método, que é justamente funcionar somente para um registro por vez.
Apesar de ter formas de atualizar mais de um registro utilizando o método update(), é mais interessante utilizar o método query() do Zend_Db, conforme veremos mais adiante.

NOTA: Nós poderíamos utilizar um formulário de cadastro para realizar estas operações CRUD, mas vamos deixar para ver isto mais adiante na autenticação e controle de usuário, pois até lá você vai ter tempo para fuçar e descobrir coisas sozinho.

Para atualizar o nosso usuário vamos primeiro criar um novo action:

 lang="plain
zf create action update usuario 1 admin

E no método updateAction():


...
    public function updateAction()
    {
        $dados = array(
	        'nome' => 'Seu Nome Aqui',
	        'email' => 'seu@email.com',
	        'login' => 'seu_login',
	        'senha' => md5('sua_senha'),
        );

        $this->_db->update( $dados, 'id = 1' );
    }
...

Modifique as informações e abra a página: http://zend.localhost/admin/usuario/update. Verifique no banco de dados que as informações foram atualizadas!

Simples, né?
O Método update() possui um parâmetro adicional que aceita o que seria as clausulas para filtrar a atualização. Se você não passar nada, ele exibirá uma mensagem de Erro mas fará a alteração em todas as linhas da tabela.

O Método delete()

Para excluir um usuário é tão fácil quando as demais operações, e o método delete() aceita um único parametro que deve conter o ID a ser excluido.

Crie outro usuário teste para termos outro ID além do 1 e não perdemos nosso querido usuário criado anteriormente.
Feito isto, vamos criar o action para excluir este usuário.

 lang="plain
zf create action delete usuario 1 admin

e no método deleteAction():


...
    public function deleteAction()
    {
        $this->_db->delete( 'id = 2' );
    }
...

Nem vou comentar! Muito fácil de entender!

O Método fetchRow()

Para obter um resultado da tabela, nós utilizamos o método fetchRow() e em casos mais específicos vamos chamar o método select() que está disponível dentro de nossa classe DbTable.

Para listar um usuário, vamos criar um action:

 lang="plain
zf create action list usuario 1 admin

E no método listAction():


...
    public function listAction()
    {
        $usuario = $this->_db->fetchRow( 'id = 1' );
        $this->view->usuario = $usuario;
    }
...

Basicamente, o resultado foi passado para a variável $usuario que vamos passar para o nosso View usuario a fim de recuperar as informações no arquivo view script list.phtml.

Abra o arquivo /modules/admin/views/scripts/usuario/list.phtml e insira o código abaixo:


<h2>Informações do Usuário</h2>
<table>
	<tr>
		<th>Nome</th>
		<td><?= $this->usuario->nome; ?>
	</tr>
	<tr>
		<th>Login</th>
		<td><?= $this->usuario->login; ?>
	</tr>
	<tr>
		<th>E-mail</th>
		<td><?= $this->usuario->email; ?>
	</tr>
</table>

Acesse a página http://zend.localhost/admin/usuario/list e você verá as informações do usuário com ID 1 listadas na tela.

NOTA: O método fetchRow() retorna um objeto. Se você desejar utilizar um array, faça a modelagem adicionando toArray(), conforme abaixo:


...
$usuario = $this->_db->fetchRow( 'id = 1')->toArray();
...

Conclusão

Nesta parte de nosso tutorial você conhece o Zend_Db_Table_Abstract e aprendeu a trabalhar com banco de dados e a criar Models através do ZF Tool. Também aprendeu como realizar as operações básicas de um CRUD.
Nas proximas partes vamos ver como criar um sistema de autenticação e conhecer outros métodos de manipulação de banco de dados.
É isto aí! Abraços do Giba!

12 comentários sobre “[ Tutorial ] Zend Framework – Parte 06”

  1. Muito bom os tutos. Finalmente estou aprendendo um pouco do zend :D. Valeu!

    Ali no “O Método fetchRow()”, no código exemplo esta public function deleteAction(), ao invés de public function listAction(). ehehe.
    To só pelo Zend_auth agora!

    Estou tendo alguns problemas com o “baseUrl”, não entendi direito seu funcionamento, seria minha sugestão você abordar um pouco sobre isso.

    Abraço!

  2. Opa Giba,

    Seguinte, la no application.ini eu criei:
    resources.frontController.baseUrl = “meusite.com.br/”

    Então na minha view eu recupero baseUrl().”/css/style.css”;?>por exemplo.

    Até aqui tudo certo, mas no meu Controller, quando utilizo o $this->_redirect(‘/admin/usuarios/’)
    após executar alguma coisa, o retorno me joga para isso:

    http://meusite.com.br/admin/usuarios/delete/id/meusite.com.br/admin/usuarios/meusite.com.br/admin/usuarios/meusite.com.br/admin/usuarios/………..

    Se eu comento a config. do application.ini, o retorno vem correto, ou seja, vai para a pagina correta.

    Desculpe a minha “leiguice”. =)

    1. Bem, olha só. A finalidade do baseUrl() não é passar o URL do site, mas sim qualquer outra base que você possa utilizar, tal como um diretorio.

      Para pegar o url do site você usa:

      < ?php echo $this->serverUrl(); ?>

      Você não precisa definir o baseUrl() se ele aponta para o próprio site.

      Você também não precisa passar o URL todo para chamar um arquivo CSS, JS ou imagem, pois o “/” já resolve isto.

      No teu caso ali:

      Para o carregamento de javascript e css você tem fazer isto no arquivo layout, certo?
      < ?php echo $this->headStyle()->appendStyle(‘/css/styles.css’);?>
      O mesmo para javascript:
      < ?php echo $this->headScript()->appendFile(‘/js/jquery.js’); ?>

      Agora se você faz questão, porque quer carregar os arquivos direto dentro dos arquivos phtml, então use o

      Responder
      1. Ola giba..é vero!
        Assim funcionou. na verdade eu defini no bootstrap $view->headLink()->prependStylesheet(‘/css/styles.css’);
        e no layout echo $this->headLink();

        O que acontece é que nao carregava o estilo se eu não usasse o baseUrl, tipo $this->baseUrl().’/css/style.css’, mas o porque disso foi que no vhosts eu passei no DocumentRoot “C:/wamp/www/meusite/public”.

        No log de erro do apache aparecia: File does not exist: C:/wamp/www/meusite/public/public. nunca iria funcionar. So tirei o “public” do documentRoot e funcionou assim como vc descreveu. Falha minha.

        Valeu pela força. Quando teremos a parte 7?

        abço!

  3. Grande Giba…

    Eu novamente com uma duvida, no inicio dos posts você nos orientou como se trabalha com modules, criamos o default e o admin, agora seu eu criar o um model pelo zf tools, ele irá criar em /application/models e não em /application/module/admin/models como podemos usar o zf tools para criar o model dentro de um module específico?
    Abraço.

    1. Opa, nossa… só vi seu comentário agora kkkkkkkk
      Meu, Desculpa cara…
      Seguinte, para se criar um model dentro de um modulo específico você deve executar o comando:

      Para criar o model em si:

      zf create model NOME_DO_MODEL NOME_DO_MODULO

      e para criar o DbTable

      zf create db-table NOME_DO_MODEL NOME_DA_TABELA NOME_DO_MODULO

      Abraço!!!

    1. Olá, caro José Ricardo.
      Os tutoriais estão parados porque estou trabalhando em alguns projetos intensos de minha empresa.
      Tão logo quanto puder, estarei dando continuidade ao mesmo.

  4. Cara, Meus parabens pelo tutorial, muita paciencia e vontade de compartilhar seus conhecimentos.
    Está sendo um ótimo ponto de partida pra aprender um pouco sobre como funciona o Zend.
    Pelo que ví no comentário acima você anda meio ocupado, mas seria otimo se pudesse continuar o tutorial.
    Parabéns de novo!

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *