Neste artigo iremos abordar o uso de joins com a classe Zend_Db_Select. Muitas consultas utilizam de joins para combinar tabelas e montar os resultados esperados, você pode adicionar tabelas ao seu select usando o método join() que é semelhante ao from(), exceto que ao usar o método join() você além de especificar a tabela e colunas de retorno, precisará especificar a condição de junção das tabelas. O método recebe dois parâmetros obrigatórios, o nome da tabela e a condição de junção, respectivamente, por último, caso seja necessário, as colunas de retorno.
Tipos de join e seus respectivos métodos da classe Zend_Db_Select
Agora vamos dar uma olhada nos tipos de joins disponíveis, quais métodos correspondem aos tipos e uma descrição simples do que é feito, acho que não é necessário nesse momento exemplificar cada tipo, pois são parecidos, o que vale nesse momento é conhecer a funcionalidade de cada um, mas caso você queira ver exemplos, de uma olhada no post, Zend Framework SQL Joins Examples.
Inner join – join(table, condition, [columns]) ou joinInner(table, condition, [columns])
Este é o tipo mais comum de join, onde as linhas de cada tabela são comparadas através de uma condição de junção, retornando apenas as linhas que satisfazem essa condição.
Left join – joinLeft(table, condition, [columns])
Ao utilizar left join, todas as linhas da tabela esquerda estarão incluídas nos resultados, caso a tabela esquerda não tenha correspondente na tabela direita, as colunas da tabela direita serão retornadas como NULL.
Right join – joinRight(table, condition, [columns])
Semelhante ao left join, no right join, todas as linhas da tabela da direta estarão incluídas nos resultados e caso a tabela da direita não tenha correspondente na tabela esquerda, as colunas da tabela da esquerda serão retornadas como NULL.
Full join – joinFull(table, condition, [columns])
Este tipo de join é uma combinação entre o left join e right join, todas as linhas de ambas as tabelas estarão incluídas nos resultados, desde que preencham a condição de junção, caso não tenha correspondente as linhas serão complementadas como NULL.
Cross join – joinCross(table, [columns])
Neste tipo de join, o resultado é um produto cartesiano, cada linha da tabela da esquerda é correspondente a cada linha da tabela da direita, para este tipo de join não é necessário definir uma condição de junção. Você pode filtrar esse tipo de join utilizando o método where.
Natural join – joinNatural(table, [columns])
Este tipo de join, faz uma comparação natural entre as tabelas, ele compara todas colunas que tenham nomes iguais em ambas as tabelas.
Métodos auxiliares da classe Zend_Db_Select
No último artigo, falamos sobre Consultas personalizadas com Zend_Db_Select e apresentamos alguns métodos da classe Zend_Db_Select, agora vamos conferir mais alguns métodos utilizados para criar nossas consultas.
distinct – Método utilizado para filtrar os resultados, selecionando apenas resultados distintos.
group – Método utilizado para organizar os resultados em grupos, sendo necessário informar o campo responsável pela organização.
having – Método utilizado para filtrar os resultados através de uma comparação sobre grupos, semelhante ao método where, sendo que o método having é usado após a definição de um grupo.
limit – Método utilizado para limitar o número de resultados de uma query, você também pode especificar quantas linhas pular antes de iniciar a contagem.
limitPage – Semelhante ao método limit que permite controlar os resultados, o método limitPage, facilita esse controle em casos de paginação, sendo necessário apenas informar a página e a quantidade de resultados exibidos por página.
union – Método utilizado para unir o resultado de duas querys, vale lembrar que não é permitido unir duas querys com campos de retorno diferente, caso tenha uma pequena diferença utilize alias para padronizar o retorno.
reset – Método utilizado para limpar todas as configurações que já tenham sido realizadas até então, para começar a criação do zero.
Usando setIntegrityCheck(false) para retornar dados da tabela match
O método setIntegrityCheck(false) é utilizado para colocar a tabela match em modo de leitura, possibilitando retornar campos dessa tabela, ou seja, ao usar o método setIntegrityCheck podemos retornar colunas da tabela match, na documentação atual não adicionaram nada sobre o método, que é muito útil na hora de criar nossas consultas usando join.
Projeto usando joins
Agora que vimos um pouco sobre join usando a classe Zend_Db_Select, vamos criar um projeto para trabalhar com join, baseado na estrutura apresentada no tópico Preparando o ambiente para desenvolvimento com Zend Framework, crie um projeto com nome de example-join.
No exemplo que será visto agora, iremos utilizar o banco apresentado no artigo Mapeando relacionamentos nos modelos, para criar nossos métodos usando join, confira o diagrama do nosso banco de dados:
Visualize ou efetue o download do script sql, no script além dos comandos de criação das tabelas, contém comandos para inserir valores nas tabelas para que o exemplo no final do artigo funcione corretamente.
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.
Criando modelos e métodos usando Join
Com o banco devidamente criado, crie os arquivos das abas abaixo na pasta “application/models”.
No modelo User, além de realizar as configurações básicas, criamos um método, findByQtdProduct($quantity), para selecionar usuários que tenham cadastrado um número igual ou acima da quantidade que é passada como parâmetro para o método, que realiza um Inner join entre as tabelas user e product e conta o numero de produtos cadastrados por cada usuário e filtra os resultados comparando com a quantidade.
No modelo Product, realizamos a configuração e o mapeamento do modelo.
No modelo Order, realizamos a configuração e o mapeamento do modelo.
No modelo OrderItem, além de realizar as configurações básicas, criamos um método, findByOrder($order), para selecionar os produtos/itens que estão relacionados a um determinado pedido, o método recebe como parâmetro o id do pedido e realiza Inner join nas tabelas order, order_item e product, retornando todos os itens do pedido com suas quantidades.
Trabalhando com joins
Com os nossos modelos criados e nossos métodos com select usando join prontos, vamos trabalhar com esses métodos, para isso vamos utilizar o IndexController.php e sua view, index.phtml.
IndexController.php
index.phtml
Estrutura final do nosso projeto:
Resultado
Ao executar nossa aplicação iremos obter o seguinte resultado:
Confira o código-fonte do exemplo no GitHub.