Entendendo modelos no zend framework

Os modelos são responsáveis pela definição das regras de negócio da aplicação, por exemplo, se na sua aplicação não é permitido que dois usuários tenham o mesmo nome, é no modelo que você define essa regra, implementando para esse caso um método “isUniqueName($name)”, para verificar se o nome já está sendo usado. Além disso os modelos são responsáveis por acessar o banco de dados, inserindo, resgatando registros, etc.

Neste tópico vamos analisar a estrutura de um modelo usando zend_db_table, como configurar nossa aplicação para ter acesso ao banco de dados e como otimizar a chamada dos modelos, além de criar uma aplicação simples usando modelos.

Entendendo a classe Zend_Db_Table

A classe Zend_Db_Table é uma interface orientada a objetos para as tabelas do banco de dados que fornece métodos para muitas operações comuns. A classe base é extensível, portanto, você pode adicionar lógica personalizada, ou seja, criar métodos para representar a sua lógica de negócio. Ao extender a classe Zend_Db_Table_Abstract nossos modelos poderão chamar todos os métodos implementados pela classe como find(),  fetchRow(), fetchAll(), insert(), update(), delete() entre outros métodos.

Recomendo a leitura da documentação sobre Zend_Db_Table, que conta com os seus recursos, alguns desses recursos veremos aqui, mas é sempre bom verificar todos os recursos disponíveis.

Trabalhando com modelo no zend framework

Agora que vimos o que é um modelo e conheçemos um pouco sobre a classe Zend_Db_Table, vamos criar um projeto usando modelos, baseado na estrutura criada no tópico Preparando o ambiente para desenvolvimento com Zend Framework, utilizando a url http://zf.example, apresentada no tópico Personalizando urls locais no wamp server, para testar nossa aplicação, crie um projeto com nome de example-models.

Estrutura do nosso projeto
Estrutura do nosso projeto

Criando nossa base de dados

Para realizar esse exemplo vamos precisar criar uma base de dados(bem simples), para trabalhar usando modelo no zend framework, nossa base contém apenas uma tabela(user), com dois campos além da chave primária, name e email.

CREATE TABLE user (
    user_id bigint(20) NOT NULL AUTO_INCREMENT,
    name varchar(50) NOT NULL,
    email varchar(100) NOT NULL,
    PRIMARY KEY(user_id)
);

Acesse o phpmyadmin, http://localhost/phpmyadmin, crie uma base de dados com o nome de “zf-models” e adicione o script acima para criar a tabela “user”.

Configurando nossa aplicação para trabalhar com modelos

Agora que nosso banco de dados foi criado vamos configurar nosso projeto, para isso vamos editar dois arquivos, application.ini e Bootstrap.php.

application.ini

[production]
phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0
includePaths.library = APPLICATION_PATH "/../library"
includePaths.models = APPLICATION_PATH "/models"
bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"
appnamespace = "Application"
resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
resources.frontController.params.displayExceptions = 0

resources.db.adapter = PDO_MYSQL
resources.db.isDefaultTableAdapter = true
resources.db.params.host = "localhost"
resources.db.params.username = "seu usuário"
resources.db.params.password = "sua senha"
resources.db.params.dbname = "zf-models"
resources.db.params.persistence = true
resources.db.params.charset = "utf8"

[staging : production]

[testing : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1

[development : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1
resources.frontController.params.displayExceptions = 1

Para trabalhar com modelos precisamos indicar o caminho onde estão armazenados, para isso adicionamos a linha 5 que adiciona a pasta “application/models” no includePaths. Além disso precisamos configurar o resource db para que a aplicação se conecte ao banco de dados, confira essa configuração na linha 12 a 19.

Bootstrap.php

<?php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
    /**
    * Init Autoloader
    */
    protected function _initAutoload()
    {
        $loader = Zend_Loader_Autoloader::getInstance();
        $loader->setFallbackAutoloader(true);
    }
}

No Bootstrap.php configuramos o autoloader para carregar nossas classes automáticamente, com essa configuração nossa aplicação está preparada para acessar nosso banco de dados e trabalhar com modelos através de chamadas simples, está não é a melhor maneira de configurar nossa aplicação para o uso de modelos, mas é a maneira ideal para iniciar os estudos sobre modelos, veremos outras configurações em outros tópicos.

Criando o modelo User

Crie o arquivo User.php na pasta “application/models” e adicione o seguinte conteúdo.

<?php
class User extends Zend_Db_Table_Abstract
{
    /**
    * The default table name
    */
    protected $_name = 'user';

    /**
    * isUniqueName
    *
    * @desc check if is unique name
    * @param <string> $name
    */
    public function isUniqueName($name)
    {
        $where = $this->getDefaultAdapter()->quoteInto('name = ?', $name);
        return (count($this->fetchAll($where)) == 0) ? true : false;
    }
}

O que fazemos aqui é simples, definimos o nome da tabela($_name = ‘user’) como um atributo protected, isso basta para que nosso modelo usando zend_db_table represente a tabela “user” do banco de dados e criamos o método isUniqueName para verificar se o nome passado por parâmetro já existe na tabela “user”, lembrando que agora que extendemos a classe Zend_Db_Table_Abstract temos todos os seus métodos implementados disponíveis.

Simulando um crud básico de usuários

Crie o arquivo “UserController.php” na pasta “application/controllers” e adicione o conteúdo abaixo:

UserController.php

<?php
class UserController extends Zend_Controller_Action
{

    /**
    * default model
    *
    * @var <User> $_model
    */
    private $_model;

    /**
    * init Controller
    */
    public function init()
    {
        $this->_model = new User();
    }

    /**
    * user list
    */
    public function indexAction()
    {
        // retorna todos os registros da tabela users
        $users = $this->_model->fetchAll();
        // envia o resultado para view
        $this->view->assign('users', $users);
    }

    /**
    * add user
    */
    public function addAction()
    {
        // simulando uma entrada de dados
        $user = array (
            'name'=>'Diogo Matheus',
            'email'=>'dm.matheus@gmail.com'
        );

        // verificando se existe registro usando esse nome
        if($this->_model->isUniqueName($user['name']))
        {
            // caso não tenha registro usando esse nome vamos inserir
            $this->_model->insert($user);
        }

        // redirecionando para lista de usuários
        $this->_helper->redirector('index', 'user');
    }

    /**
    * update user
    */
    public function editAction()
    {
        // simulando uma entrada de dados
        $data = array (
            'email'=>'diogo.matheus@msn.com'
        );

        // atualizando o email do usuário Diogo Matheus
        $where = $this->_model
                      ->getDefaultAdapter()
                      ->quoteInto('name = ?', 'Diogo Matheus');
        $this->_model->update($data, $where);

        // redirecionando para lista de usuários
        $this->_helper->redirector('index', 'user');
    }

    /**
    * delete user
    */
    public function removeAction()
    {
        // removendo o usuário Diogo Matheus
        $where = $this->_model
                      ->getDefaultAdapter()
                      ->quoteInto('name = ?', 'Diogo Matheus');
        $this->_model->delete($where);

        // redirecionando para lista de usuários
        $this->_helper->redirector('index', 'user');
    }
}

Começamos a configuração do controller adicionando o atributo “$_model”, que representa o modelo principal daquele controller, afinal no controller UserController é esperado que o modelo User seja o mais utilizado.

Depois o que fazemos nesse controller é criar uma estrutura de actions visando as operações básicas de um modelo, visualizar as informações da tabela, adicionar, editar e remover. Na action add, antes de adicionar o registro na tabela, verificamos se o nome já existe, caso exista o usuário não é adicionado, lógico que em uma aplicação real isso seria contornado, por exemplo com uma mensagem, mas como essa aplicação só visa passar o conhecimento sobre os modelos é melhor deixar o mais simples e funcional possível.

Agora vamos preparar uma view de listagem de usuários, crie a pasta “user” em “application/views/scripts” e depois adicione o arquivo index.phtml com o seguinte conteúdo:

index.phtml

<?php if(count($this->users)): ?>
<ul>
    <?php foreach($this->users as $user): ?>
    <li><?php echo $user->name; ?> - <?php echo $user->email; ?></li>
    <?php endforeach; ?>
</ul>
<?php else: ?>
    <?php echo 'Nenhum registro foi encontrado.'; ?>
<?php endif; ?>

Pronto, nossa view está preparada para listar os usuários e se precisar exibir uma mensagem caso não tenha registros.

Confira a estrutura final do nosso projeto:

Estrutura final do nosso projeto
Estrutura final do nosso projeto

Testando nossa aplicação

Com nossa aplicação finalizada, vamos realizar alguns testes, siga o fluxo das tabelas abaixo e verifique se os resultados serão os mesmos.

Listagem

Acesse http://zf.example/user para visualizar a página de listagem de usuários

Resultado sem registros
Resultado sem registros

O resultado será uma mensagem de que nenhum registro foi encontrado.

1º Adição

Acesse http://zf.example/user/add para adicionar um usuário (simulado no controller)

Resultado com um registro
Resultado com um registro

O resultado será um registro na lista de usuários, porque no final da action somos redirecionados para página de listagem.

2º Adição

Acesse http://zf.example/user/add para tentar adicionar o mesmo usuário novamente

Resultado com um registro
Resultado com um registro

O resultado será a listagem ainda com apenas um registro, porque o nome “Diogo Matheus” já existe na tabela “users” fazendo o método isUniqueName retornar false.

Editando

Acesse http://zf.example/user/edit para editar o email do usuário

Resultado com registro editado
Resultado com registro editado

O resultado será a listagem com apenas um registro, mas com o email diferente.

Removendo

Acesse http://zf.example/user/remove para remover o usuário

Resultado sem registros
Resultado sem registros

O resultado será uma mensagem de que nenhum registro foi encontrado, porque acabamos de remover o único registro.

Visualizar ou efetuar download do exemplo, lembrando que no repositório desse projeto no github não consta os arquivos do framework.

  • Mapeando relacionamentos nos modelos

    16/05/2011 às 08:58

    […] Início « Entendendo modelos no zend framework […]

  • Consultas personalizadas com Zend_Db_Select

    30/05/2011 às 11:42

    […] Acesse o phpmyadmin, crie o banco “zf-order” e execute o script sql acima para criar e preencher as tabelas do banco. Após criar o banco edite o arquivo application.ini com as informações do banco de dados, caso tenha dúvida, visualize o artigo Entendendo modelos no zend framework. […]

  • Realizando joins no zend framework

    12/06/2011 às 18:11

    […] Acesse o phpmyadmin, crie o banco “zf-order” e execute o script sql acima para criar e preencher as tabelas do banco. Após criar o banco edite o arquivo application.ini com as informações do banco de dados, caso tenha dúvida, visualize o artigo Entendendo modelos no zend framework. […]

  • Customizando modelos no zend framework | Diogo Matheus Blog

    03/12/2011 às 20:41

    […] Acesse o phpmyadmin, crie o banco “zf-order” e execute o script sql acima para criar e preencher as tabelas do banco. Após criar o banco edite o arquivo application.ini com as informações do banco de dados, caso tenha dúvida, visualize o artigo Entendendo modelos no zend framework. […]

  • Realizando joins no zend framework | Diogo Matheus Blog

    27/02/2012 às 22:30

    […] Acesse o phpmyadmin, crie o banco “zf-order” e execute o script sql acima para criar e preencher as tabelas do banco. Após criar o banco edite o arquivo application.ini com as informações do banco de dados, caso tenha dúvida, visualize o artigo Entendendo modelos no zend framework. […]

  • Fabio

    08/11/2012 às 21:36

    Diogo, primeiramente quero te parabenizar pelos excelentes posts que você tem no blog.

    Mas Deixa eu te fazer uma pergunta…

    To começando um novo projeto e gostaria de usar Zend, porem estou com muitas dúvidas em relação a qualidade e produtividade.

    Estou querendo usar uma camada de model e uma de DbTable, mas a questão é…

    É bom usar os métodos mágicos do zend? Por exemplo ele mapear as colunas da tabela para inserção e atualização?

    Fico muito na dúvida se uso os métodos que faz tudo do zend e ter problema de performance.

    Como você faz no seu dia a dia?

    Grato pelo retorno

  • Diogo Matheus

    11/11/2012 às 10:39

    Fabio, minha parte de models em ZF 1 normalmente fica da seguinte maneira: Model, DbTable, Mapper/Manager. No Model tenho apenas os atributos de cada model e métodos para facilitar tanto construir um objeto através de um array quanto transformar ele em array, no DbTable tenho apenas as configurações de acesso a determinada tabela, row e rowset class, já no Mapper/Manager é onde costumo criar métodos de acesso utilizando o DbTable, nesse caso com transações no Mapper/Manager.

  • Trabalhando com paginação usando Zend_Paginator | Diogo Matheus

    08/02/2015 às 21:25

    […] Obs: Configure a aplicação para acessar o banco de dados “zf-paginator”, caso tenha dúvida, visualize o artigo Entendendo modelos no zend framework. […]

  • Rodrigo

    29/04/2016 às 15:10

    Olá Diogo!

    Excelente artigo. Vi um outro artigo em que o cidadão colocava as instruções para o banco na camada Model. O que você acha desta abordagem? No meu ver, se há o esquema MVC, não deveria ser a chamada via Controller como você fez? Um exemplo do que citei em que o cidadão faz direto no model isso é este link abaixo que confesso, confundiu (rs) o meu conceito de MVC. A Zend instiga que seja feito o acesso via model (implementação no model) ou estamos certos em manter no Controller?

    http://www.devmedia.com.br/criando-um-projeto-com-zend-framework/32175

    Obrigado,
    Rodrigo

Deixe uma resposta

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