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.
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”.
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 "<b>" . $this->nome . "</b>";
}
}
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();
}
}
Espero que esse post te ajude a desenvolver aplicações Zend utilizando o máximo de recursos que esse Framework oferece!