05
jun

Relacionamento de tabelas no Zend Framework utilizando o Zend_Db_Table

Estou utilizando o Zend na sua versão mais recente, a 1.10.5, e o objetivo desse post é mostrar como relacionar tabelas com Zend_Db_Table e a utilidade do Zend_Db_Table_Row.


Apesar de não ser o objetivo do post, vou utilizar também o Zend_Loader para facilitar o carregamento das classes.


Para baixar o exemplo completo, clique aqui.


Na pasta lib/Zend você deve colocar o Framework Zend, que não incluí no download para deixá-lo mais leve.


A estrutura de pastas será a seguinte:


PastaRoot
-- Model
-- lib
---- Zend


Na pasta Model iremos colocar as classes referentes as tabelas do banco e na pasta lib/Zend ficará o Framework em si.


Como não é o objetivo do post, não irei implementar a estrutura de MVC do Zend, apenas o Zend_Db. Essa é uma das vantagens do Zend, a possibilidade de usar apenas uma parte do Framework sem depender das restantes.


Antes de tudo você deve criar um banco no seu MySQL, será o banco que utilizaremos no exemplo. Ele deve ter uma tabela “site” e uma tabela “pagina”. A estrutura das tabelas e seus inserts estão no arquivo de download com o nome “exemplo.sql”.


Crie um arquivo no root do exemplo como o nome de index.php, será toda a nossa aplicação. Vamos começar incluindo a pasta de biblioteca e Model no include_path:


/**
 * Inclui a pasta lib e Model no include path
 */
define('ROOT_DIR', dirname(__FILE__));
set_include_path(get_include_path() . PATH_SEPARATOR .
        ROOT_DIR . '/lib/' . PATH_SEPARATOR .
        ROOT_DIR . '/Model/');


Logo depois iremos utilizar o Zend_Loader para não termos de chamar as classes separadamente:


/**
 * Inclui e instancia o Autoloader
 */
include('Zend/Loader/Autoloader.php');
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->setFallbackAutoloader(true);


Agora iremos realizar a conexão com o banco e registrarmos esse adaptador como default:


/**
 * Conecta ao banco e registra o adaptador
 */
$db = Zend_Db::factory('Pdo_Mysql', array(
    'host'     => 'localhost',
    'username' => 'root',
    'password' => '',
    'dbname'   => 'ZendDb'
));
Zend_Db_Table_Abstract::setDefaultAdapter($db);


Perfeito! Nesse momento temos a aplicação incluindo as pastas necessárias no include_path, instanciando o Autoloader e fazendo a conexão com o banco.


Agora vamos criar as classes de cada tabela na pasta Model. Vamos começar com a tabela “site”, para isso crie um arquivo Sites.php na pasta Model com o conteúdo:


class Sites extends Zend_Db_Table{

    /**
     * Define o nome da tabela
     */
    protected $_name = 'site';

    /**
     * Define a primary key
     */
    protected $_primary = 'id';

    /**
     * Define a classe que irá
     * lidar com cada linha
     */
    protected $_rowClass = 'Site';

}


No atributo $_name definimos o nome da tabela que a classe irá cuidar, no atributo $_primary definimos a primary key dessa tabela e no atributo $_rowClass definimos o nome da classe que irá cuidar de cada registro dessa tabela como objeto, a tabela “rowClass” é especialmente útil pois poderemos cuidar de cada registro separadamente, ou seja, se quisermos mostrar o nome do site já formatado não precisamos tratar esse atributo, apenas chamamos um método que fará essa formatação, e agora iremos criar essa classe.


Crie um arquivo com o nome Site.php também na pasta Model com o seguinte conteúdo:


class Site extends Zend_Db_Table_Row {

    /**
     * Formata o nome do site
     */
    public function nomeFormatado(){
        return "" . $this->nome . "";
    }

}


Agora todas as vezes que você estiver lidando com uma linha da tabela “site” e quiser mostrar o nome formatado, basta chamar o método nomeFormatado().


Vamos então criar a classe que cuidará da tabela “pagina”, para isso crie um arquivo com o nome de Paginas.php na pasta Model:


class Paginas extends Zend_Db_Table{

    /**
     * Define o nome da tabela
     */
    protected $_name = 'pagina';

    /**
     * Define a primary key
     */
    protected $_primary = 'id';

    /**
     * Define a classe que irá
     * lidar com cada linha
     */
    protected $_rowClass = 'Pagina';

    /**
     * Cria o relacionamento entre a
     * tabela "pagina" e a tabela "site"
     */
    protected $_referenceMap    = array(
        'SitePagina' => array(
            'columns'           => 'id_site',
            'refTableClass'     => 'Sites',
            'refColumns'        => 'id'
        ),
    );

}


Ela segue o mesmo padrão da classe da tabela “site”, com a diferença do atributo $_referenceMap, que será o responsável por criar o relacionamento entre as tabelas.


Esse atributo é um array com outro array dentro dele, onde o nome da posição do primeiro array é apenas um nome criado por nós que nomeará esse relacionamento, esse nome pode ser o que você quiser e nesse exemplo não influenciará em nada, dei o nome de “SitePagina”.


Dentro do array que ficará na posição “SitePagina” temos outras três posições:


- columns: Especifica qual a coluna que fará referência com a outra tabela, nesse caso, será a coluna “id_site” da tabela “pagina” que fará referência ao “id” da tabela “site”;


- refTableClass: Qual a classe responsável pela tabela de referência, nesse caso será a classe “Sites”;


- refColumns: Qual a coluna na tabela de referência que deverá ser relacionada com essa tabela;


E agora como fizemos na tabela “site” vamos criar uma classe para a tabela “pagina” que cuidará de cada registro dela. Para isso crie um arquivo Pagina.php dentro da pasta Model:


class Pagina extends Zend_Db_Table_Row {

    /**
     * Formata o nome da página
     */
    public function nomeFormatado(){
        return "- " . $this->nome . "";
    }

}


Ela terá a mesma função da classe da tabela “site”, apenas formatará o nome quando chamarmos o método nomeFormatado().


Nesse momento já criamos todas as classes que cuidarão das tabelas do banco e farão seu relacionamento. Vamos continuar nosso arquivo index.php:


/**
 * Instancia a classe que lidará com a
 * tabela 'site'
 */
$tableSite = new Sites();

/**
 * Seleciona todas as linhas da tabela
 * ordenando por nome
 */
$siteRowSet = $tableSite->fetchAll(
                                $tableSite->select()
                                ->order('nome')
                            );


Agora instanciamos a classe que cuidará da tabela “site” e pedimos a ele um rowset com todos os registros ordenados por nome, e seguimos em frente:


/**
 * Passa linha por linha da lista de
 * registros da tabela 'site'
 */
foreach($siteRowSet as $rowSite){


Com a rowset em mãos, que não passa de um array com todos os objetos referentes a cada registro da tabela, iremos percorrê-lo:


	/**
     * Chama um método que devolve o nome formatado.
     * Esse já é um objeto da classe Site
     * ou seja, uma classe Zend_Db_Table_Row
     */
    echo $rowSite->nomeFormatado();


Como estamos percorrendo um rowset da tabela “site”, cada posição desse array é um objeto referente ao registro da tabela, e como definimos uma classe para cuidar disso, estamos lidando com um objeto dessa classe, ou seja, o método que formata o nome pode ser chamado, é o que fizemos.


Prosseguindo:


	/**
     * Chamamos um método do objeto que irá
     * retornar uma lista de objetos relacionados
     * da tabela páginas
     */
    $paginaRowSet = $rowSite->findDependentRowset('Paginas');


Agora chamamos o método findDependentRowset() do objeto da tabela “site” e esse método irá retornar todos os registros da tabela “pagina” que fazem referência a esse registro da tabela “site”. Ele retorna também um rowset. Agora vamos iterar ele e mostrar o nome da cada página referente ao site:


	/**
     * Para cada registro da lista de páginas
     * imprime o nome da página usando o objeto
     */
    foreach($paginaRowSet as $rowPagina){

        /**
         * Imprime o nome da página usando um
         * método da classe Pagina, uma
         * classe Zend_Db_Table_Row
         */
        echo $rowPagina->nomeFormatado();
    }
}


Pronto! Você acaba de mostrar uma lista de sites e suas referidas páginas utilizando o relacionamento do Zend_Db_Table. E o arquivo index.php completo deve ficar assim:


/**
 * Inclui a pasta lib e Model no include path
 */
define('ROOT_DIR', dirname(__FILE__));
set_include_path(get_include_path() . PATH_SEPARATOR .
        ROOT_DIR . '/lib/' . PATH_SEPARATOR .
        ROOT_DIR . '/Model/');

/**
 * Inclui e instancia o Autoloader
 */
include('Zend/Loader/Autoloader.php');
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->setFallbackAutoloader(true);

/**
 * Conecta ao banco e registra o adaptador
 */
$db = Zend_Db::factory('Pdo_Mysql', array(
    'host'     => 'localhost',
    'username' => 'root',
    'password' => '',
    'dbname'   => 'ZendDb'
));
Zend_Db_Table_Abstract::setDefaultAdapter($db);

/**
 * Instancia a classe que lidará com a
 * tabela 'site'
 */
$tableSite = new Sites();

/**
 * Seleciona todas as linhas da tabela
 * ordenando por nome
 */
$siteRowSet = $tableSite->fetchAll(
                                $tableSite->select()
                                ->order('nome')
                            );

/**
 * Passa linha por linha da lista de
 * registros da tabela 'site'
 */
foreach($siteRowSet as $rowSite){

    /**
     * Chama um método que devolve o nome formatado.
     * Esse já é um objeto da classe Site
     * ou seja, uma classe Zend_Db_Table_Row
     */
    echo $rowSite->nomeFormatado();

     /**
     * Chamamos um método do objeto que irá
     * retornar uma lista de objetos relacionados
     * da tabela páginas
     */
    $paginaRowSet = $rowSite->findDependentRowset('Paginas');

    /**
     * Para cada registro da lista de páginas
     * imprime o nome da página usando o objeto
     */
    foreach($paginaRowSet as $rowPagina){

        /**
         * Imprime o nome da página usando um
         * método da classe Pagina, uma
         * classe Zend_Db_Table_Row
         */
        echo $rowPagina->nomeFormatado();
    }
}


IMPORTANTE! Nesse post não coloquei a tag de abertura (<?php) e fechamento (?>) do PHP para facilitar a inclusão dos códigos, não se esqueça delas.


Espero que esse post te ajude a desenvolver aplicações Zend utilizando o máximo de recursos que esse Framework oferece!

4 comentários para “Relacionamento de tabelas no Zend Framework utilizando o Zend_Db_Table”

  1. Jus-SC disse:

    Olá Pedro, boa tarde.
    Seguinte, vendo este tutorial e sabendo de seu conhecimento em Magento, quero lhe perguntar, qual ferramenta utilizar para desenvolver em magento?

    para criar modulos, editar funções, classes, enfim, para trabalhar com a estrutura do magento, qual combinação de IDE, Framework, plugin… vc aconselha?

    Grato

    Responder

    Pedro Teixeira respondeu:

    @Jus-SC,

    Você pode usar qualquer IDE PHP, a que você mais gostar. Pessoalmente gosto do Netbeans, acho ele bem completo.

    De resto é só colocar a mão na massa.

    Abraço!

    Responder

    Jus-SC respondeu:

    @Pedro Teixeira, certo, eu tbm gosto do NetBeans, mas para desenvolver em JAVA.
    Para trabalhar com o padrão da Zend, tem algum plugin? algo que facilite os processo? ou realmente ou precisar programar magento com a documentação do lado para consultar funções, classes, localizar os arquivos, banco, tabelas….

    Responder

    Pedro Teixeira respondeu:

    @Jus-SC,

    Existe uma versão do NetBeans para PHP: http://netbeans.org/features/php/

    Não utilizo nenhum plugin, mas se sua preocupação é achar as classes do Zend é só segurar o ctrl e clicar no nome da classe que ele encontra e abre para você, a mesma coisa funciona com métodos e atributos.

    Abraço!

    Responder

Deixe um comentário