HUFERSIL.WEBDEVELOPER

Lumine – Tutorial 5 – Trabalhando com joins

Hoje vamos ver como trabalhas com joins no Lumine.
Ele torna o trabalho bem mais fácil e humanamente falando mais claro de se entender.
Caso você não tenha feito, faça as etapas anteriores para se familiarizar com o processo:

Vamos fazer um inner join simples, cruzando as entidades de Categoria e Noticia.

Antes de qualquer consulta que vamos realizar que exije o cruzamento de uma ou mais tabelas, temos que lembrar a seguinte regra: qual é a fonte de dados principal que eu desejo extrair os dados?

Neste primeiro exemplo, nós queremos listar as notícias e o nome da categoria das mesmas. Sendo assim, vamos trabalhar com a entidade de Noticia para recuperar os dados desejados.

Vejamos o primeiro exemplo de código:

<?php

// importa as configurações padrãorequire_once 'config.php';

// importa as classes de categoria e noticiaLumine::import('Categoria','Noticia');

// inicia um objeto de categoria$categoria = new Categoria();

// inicia um objeto de noticia$noticia = new Noticia();

////////////////////////////////////////////////////////// agora, vamos fazer a união////////////////////////////////////////////////////////

// mudamos o alias de noticia $noticia->alias('n')    // unimos com categoria, colocando o alias c    ->join($categoria,'inner','c')    // selecionamos os campos desejados    ->select('n.codnoticia, n.titulo, n.data_cadastro, n.categoria, c.nome as nomecategoria')    // ordenamos pela data de cadatro da notícia decrescente    ->order('n.data_cadastro desc')    // efetuamos a consulta    ->find();

// para cada resultado encontradowhile( $noticia->fetch() ){    // mostramos o codigo da noticia, titulo e categoria    echo $noticia->codnoticia . ' - ' .        $noticia->titulo . ' - ' .         $noticia->nomecategoria . '<br>'; }

Salve o arquivo com o nome de join.php

O primeor argumetno da chamada ao join, é um objeto instanciado que extende a classe Lumine_Base, que no nosso caso é $categoria. O segundo argumento (inner), indica que vamos fazer um INNER JOIN, ou seja, toda notícia DEVE ter uma categoria. Caso a notícia não esteja vinculada a uma categoria, o registro não será retornado. E no terceiro paramêtro indicamos qual o alias (apelido) da entidade que vamos usar.

Agora vamos a um outro exemplo: vamos supor que você deseja saber quantas notícias há em cada categoria. Logo, o dado principal que queremos é a categoria. Então, ao invés de usarmos a entidade de Noticia como principal, vamos usar a de Categoria.
Vejamos o exemplo:

// mudamos o alias de categoria $categoria->alias('c')    // une com noticias no modo LEFT JOIN    ->join($noticia, 'left', 'n')    // seleciona o codigo da categoria, nome e a quantidade de notícias    ->select('c.codcategoria, c.nome, COUNT(n.codnoticia) AS total_noticias')    // ordena pelo nome da categoria    ->order('c.nome ASC')    // agrupa pelo código da categoria    ->group('c.codcategoria')    // efetua a consulta    ->find();

// para cada resultado encontradowhile( $categoria->fetch() ){    // mostramos o codigo da categoria, nome da categoria e quantidade de noticias    echo $categoria->codcategoria . ' - ' .        $categoria->nome . ' - ' .         $categoria->total_noticias . '<br>'; }

Salve o arquivo com o nome de categorias.phpi

Neste segundo exemplo, fizemos duas coisas diferentes: ao invés de usar INNER, usamos LEFT. Isto por que o que nos interessa são as categorias e quantas notícias há em cada uma. Ao contrário do INNER, o argumento LEFT faz com que os resultados da consulta principal (categorias) sejam obtidos mesmo sem a presença dos dados secundários (noticia), isto por que uma categoria poderia ter sido recém cadastrada, não tendo nenhuma notícia vinculada.

Em seguida, por estarmos usando uma função interna do banco (count) que exige de agrupamento de resultados, temos que indicar por qual campo desejamos agrupas os registros encontrados. Como desejamos pegar todas as categorias, o melhor a ser feito é agrupar pela chave-primária, pois ela é única e não pode ser nula. Na entidade Categoria, nossa chave primária é o campo codcategoria.

Tá, mas e se eu tiver que cruzar mais entidades?

A quantidade de entidades que podem ser unidas em uma mesma consulta é ilimitada. Você pode unir várias entidades para realizar uma consulta complexa, caso seja essa sua necessidade.

Vou mostrar um exemplo que utilizei em um site de um cliente:

// recupera a franquia atual do sistema (NÃO FAZ PARTE DO PACOTE DO Lumine)$franquia = $sis->getFranquia();

// instancia as classes necessárias$imovel   = new Imovel;$tipo     = new Tipo_imovel;$cidade   = new Cidade;$bairro   = new Bairro;$cliente  = new Cliente;$foto     = new Clienteimovelfoto;$cat      = new Categoria();

//////////////////////////////////////////////////// destaques da esquerda (ALTO PADRAO)////////////////////////////////////////////////$imovel->alias('i')                                // muda o alias de imovel	->join($tipo,'inner','t')                  // une com o tipo de imovel com alias t	->join($cidade,'inner','c')                // une com cidade com alias c	->join($bairro,'inner','b')                // une com bairro e alias b	->join($cliente->alias('cl')               // une com cliente com alias cl E cliente une com...		->join($franquia,'inner','fr')     // ... a franquia que ele pertence com alias fr	)	->join($foto,'left','f')                   // une com a foto do imovel (LEFT) e alias f

	// pega todos os dados de imovel	->selectAs()	// seleciona mais alguns dados	->select('b.nome as nomebairro,t.nome as nometipo,c.nome as nomecidade,f.arquivo, fr.permalink as nomefranquia')	// limpa todas as condições WHERE que existirem (se existirem)	->where()	// somente clientes ativos que não tenham expirado e imóveis que estejam ativos	->where('cl.ativo = 1 and cl.dataexpira >= ? and i.ativo = 1', time())	// somente se a franquia está ativa e que o codigo seja da franquia selecionada	->where('fr.ativo = 1 and fr.idfranquia = ?', $franquia->idfranquia)	// somente imoveis marcados como "alto padrão"	->where('i.altopadrao = 1')	// ordena randomicamente (pega a função do banco)	->order( $imovel->_getConnection()->random() )	// limita em 3 registros	->limit( 3 )	// agrupa pelo id do imovel	->group('i.idimovel')	// efetua a consulta	->find();

Este "pequeno" trecho irá gerar a seguinte consulta:

SELECT i.idimovel as idimovel, i.idbairro as bairro, i.idcidade as cidade, i.idtipo as tipo_imovel, i.idlocador as clientelocador, i.idcliente as cliente, i.nome as nome, i.logradouro as logradouro, i.numero as numero, i.descricao as descricao, i.qtd_quarto as qtd_quarto, i.qtd_suite as qtd_suite, i.qtd_sala as qtd_sala, i.qtd_cozinha as qtd_cozinha, i.terreno_largura as terreno_largura, i.terreno_comprimento as terreno_comprimento, i.area_construida as area_construida, i.venda as venda, i.locacao as locacao, i.ativo as ativo, i.destaque as destaque, i.valor_aluguel as valor_aluguel, i.valor_venda as valor_venda, i.data_cadastro as data_cadastro, i.areautil as areautil, i.areatotal as areatotal, i.idcategoria as categoria, i.altopadrao as altopadrao, b.nome as nomebairro, t.nome as nometipo, c.nome as nomecidade, f.arquivo, fr.permalink as nomefranquia FROM imo_imovel iINNER JOIN imo_tipo_imovel t ON t.idtipo = i.idtipoINNER JOIN imo_cidade c ON c.idcidade = i.idcidadeINNER JOIN imo_bairro b ON b.idbairro = i.idbairroINNER JOIN imo_cliente cl ON cl.idcliente = i.idclienteINNER JOIN imo_franquia fr ON fr.idfranquia = cl.idfranquiaLEFT JOIN imo_clienteimovelfoto f ON f.idimovel = i.idimovel WHERE cl.ativo = 1 and cl.dataexpira >= '2008-04-29' and i.ativo = 1 AND fr.ativo = 1 and fr.idfranquia = 1 AND i.altopadrao = 1 GROUP BY i.idimovel ORDER BY rand()LIMIT 3

@braços e fiquem com Deus!

Deixar uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *

*

Pode usar estas etiquetas HTML e atributos: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">