O uso de frameworks facilita cada vez mais o trabalho dos desenvolvedores web. No caso da linguagem PHP, um framework que se destaca é o Zend Framework (ZF). Compatível com PHP 5, tem o objetivo de facilitar o desenvolvimento de aplicações em geral com base no reuso de código por meio de componentes.

Uma forma de melhorar a produtividade de desenvolvimento é já utilizar componentes que fazem o “trabalho sujo” de conexão a banco de dados e manipulação de dados. Aqui, explicaremos o passo-a-passo de como relacionar as tabelas do seu banco de dados utilizando o Zend_Db_Table.

Mãos à massa

Neste exemplo, estamos usando a versão mais recente do Zend (no momento deste post), a 1.10.5. Também usaremos o Zend_Loader, que facilitará o carregamento das classes. Baixe o exemplo completo: exemplo_zend_uol_host.

Crie uma pasta lib/Zend na raiz do seu site, onde você deverá colocar o Framework Zend, que pode ser baixado aqui.

Teremos a seguinte estrutura de pastas:

public_html
-- Model
-- lib
---- Zend

As classes que referem-se às tabelas do banco de dados devem ser colocadas na pasta Model e na pasta lib/Zend colocaremos o framework. Uma vantagem do Zend é que não precisamos usar o framework inteiro, mas sim a parte que é necessária para o funcionamento dos nossos scripts.

O primeiro passo é criar um banco de dados MySQL que será usado no exemplo. Crie duas tabelas, uma chama “site” e outra “pagina” – sem aspas. A estrutura das tabelas e seus inserts estão no arquivo que disponibilizamos para download, chamado: “exemplo.sql”.

Crie um arquivo na pasta “public_html” denominado index.php que será responsável por 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/');
?>

Agora, para não termos de chamar as classes separadamente, ativaremos o Zend_Loader:

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

Faremos a conexão com o banco de dados e registraremos este adaptador como default (padrão):

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

Pronto, agora temos a aplicação incluindo as pastas do include_path, instanciando o Autoloader e fazendo a conexão com o banco. Vamos dar um segundo passo: Criar as classes de cada tabela na pasta Model. Começaremos com a tabela “site”. Para isso, crie um arquivo chamado “sites.php” na pasta Model com o seguinte 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 nós definimos o nome da tabela que a classe irá cuidar, no $_primary definimos a primary key desta tabela e no $_rowClass definimos o nome da classe que cuidará de cada registro da 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 precisaremos tratar este atributo, apenas chamamos um método que fará essa formatação.

Crie um arquivo chamado “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ê lidar com uma linha da tabela “site” e quiser mostrar o nome formatado, basta chamar o método nomeFormatado(). Criaremos agora a classe que cuidará da tabela “pagina”. Crie um arquivo chamado “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 a mesma idéia da classe da tabela “site”, porém o atributo $_referenceMap 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. Demos 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á a 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 que neste caso será a classe “Sites”;
- refColumns: Qual a coluna na tabela de referência que deverá ser relacionada com essa tabela.

Assim como fizemos na tabela “site”, vamos criar uma classe para a tabela “pagina”, que cuidará de cada registro dela. Crie um arquivo chamado “pagina.php” dentro da pasta Model com o seguinte conteúdo:

<?
class Pagina extends Zend_Db_Table_Row {

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

}
?>

Terá a mesma função da classe da tabela “site”, apenas formatará o nome quando chamarmos o método nomeFormatado(). Nesse momento nós já criamos todas as classes que cuidarão das tabelas do banco e farão seu relacionamento. Vamos continuar editando o 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')
);
?>

Instanciamos a classe que cuidará da tabela “site” e pedimos a ele um rowset com todos os registros ordenados por nome. Seguimos em frente:

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

Com o 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 deste 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.

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

Agora nós 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 também retorna um rowset. Vamos alterar ele e mostrar o nome de 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. O exemplo completo está disponível para download: exemplo zend uolhost.

Este post foi feito por Pedro Teixeira, analista de sistemas do UOL HOST.