Um pouco mais de como usar o Zend_Db_Select

/* Esta é uma continuação do post Usando o Zend_Db_Select para abstração de consultas */

As consultas a banco de dados não se limitam a apenas um SELECT * FROM `tabela`. Mais temos outros milhares de recursos a utilizar que precisam ser explorados para que nossos sistema sejam funcionais.

Você também pode usar a maior parte dos métodos do objeto Zend_Db_Select com uma interface fluent. Uma interface fluent significa que cada método retorna uma referência para o objeto no qual foi chamado, então você pode imediatamente chamar outro método.

<?php
$select = $db->select()
             ->from ( ...tabelas... )
             ->where( ...Critérios... )
             ->order( ...Ordem... );

Não entendeu? Vou explicar!

quando você chama o método select(),  este retorna uma instância do Zend_Db_Select e passa a esta instância a referencia da classe que esta chamando. Abaixo apresento como o método select() esta criada:

<?php
public function select()
{
    return new Zend_Db_Select($this);
}

Ou seja ela retorna uma instância da classe Zend_Db_Select. Agora os demais métodos tem como retorno a instância que o contém, assim:

<?php
public function where($cond, $value = null, $type = null)
{
    $this->_parts[self::WHERE][] = $this->_where($cond, $value, $type, true);
    return $this;
}

Isso é utíl para agilizar o desenvolvimento, e será usado assim daqui para a frente.  Veja como fizemos no post anterior:

<?php
$select = $db->select();
$select->from('teste');
$stmt = $select->query();
$result = $stmt->fetchAll();

Agora faremos assim:

<?php
$stmt = $db->select ()
           ->from ( 'teste' )
           ->query ();
$result = $stmt->fetchAll ();

É bem mais simples de programar e entender o que se esta fazendo, já que temos aninhado os métodos.

A cláusula from()

No método from() definimos o nome da tabela, ou das tabelas que faremos a consulta, as colunas e o schema. Para as tabelas você pode passar apenas uma tabela como string ou mais de uma tabela através de array.

<?php 
$select->from ( 'tabela' );

ou

<?php 
$select->from ( array('tabela1', 'tabela2', 'tabela3') );

No segundo parâmetro informamos as colunas que serão retornadas na consultas. Se for omitido, o valor padrão é '*'. Neste caso também pode ser informado somente uma string no caso de selecionar apenas uma coluna, ou um array para várias colunas ou se nada informado será definido como '*'.

<?php 
$select->from ( 'tabela' );

ou

<?php 
$select->from ( 'tabela', 'coluna1' );

ou

<?php 
$select->from ( 'tabela', array('coluna1', 'coluna2') );

E o ultimo parâmetro é informado o schema. No caso do MySql estamos informando o schema no Zend_Config e não será necessário informar novamente aqui.

A cláusula WHERE

A coisa mais rara que temos em um sistema é uma consulta sem WHERE, ou mesmo uma consulta sem LIMIT. No Zend_Db_Select definimos o WHERE através do método where($cond, $value, $type). Pode ser informado quantos where() for necessário até suprir todos as condições de pequisa.

<?php
$stmt = $db->select ()
           ->from ( 'teste' )
           ->where('USUARIO_ID = 1')
           ->query ();
$result = $stmt->fetchAll ();

A pesquisa acima seleciona apenas o registro 1. Se o valor  for informado através de parametro que é enviado pelo usuário, podemos fazer assim:

<?php
$stmt = $db->select ()
           ->from ( 'teste' )
           ->where('USUARIO_ID = ?', $_POST['USUARIO_ID'])
           ->query ();
$result = $stmt->fetchAll ();

Agora o Zend_Db_Select valida este dado que vem através de eformulário e se um usuário FDP mau intencionado tentar enviar algo malicioso, será bloqueado.

Se precisarmos condição OR na consulta é só passar através do método orWhere():

<?php
$stmt = $db->select ()
           ->from ( 'teste' )
           ->where('USUARIO_ID = 1')
           ->orWhere('USUARIO_ID = 2')
           ->query ();
$result = $stmt->fetchAll ();

A resposta deste ultimo será duas linhas do nosso banco de dados:

Array
(
    [0] => Array
        (
            [USUARIO_ID] => 1
            [USUARIO_NOME] => Usuario 1
        )
    [1] => Array
        (
            [USUARIO_ID] => 2
            [USUARIO_NOME] => Usuario 2
        )
)

Não há suporte a envio de array no método where().

A cláusula ORDER BY

A ordem da resposta é informada através do método order($spec) do Zend_Db_Select.

<?php
$stmt = $db->select ()
           ->from ( 'teste' )
           ->order('USUARIO_ID')
           ->query ();
$result = $stmt->fetchAll ();

A ordenação pode ser informada também  através de array, com todas as opções de ordem.

<?php
$stmt = $db->select ()
           ->from ( 'teste' )
           ->order( array( 'USUARIO_ID', 'USUARIO_NOME' ) )
           ->query ();
$result = $stmt->fetchAll ();

Se a ordem for onmitida será considerado ASC mais poder ser informado tanto como ASC comno para DESC:

<?php
$stmt = $db->select ()
           ->from ( 'teste' )
           ->order( array( 'USUARIO_ID ASC', 'USUARIO_NOME DESC' ) )
           ->query ();
$result = $stmt->fetchAll ();

A cláusula LIMIT

A limitação no resultado é informado através da cláusula limit($count, $offset) que deve ser especificado o número total de registros que será retornado e ponto de início.

<?php
$stmt = $db->select ()
           ->from ( 'teste' )
           ->limit(1, 2)
           ->query ();
$result = $stmt->fetchAll ();

No exemplo acima é retornado um item, a partir do 3 item. Lembrando que o primeiro registro inicia de Zero.

A cláusula GROUP BY

A cláusula GROUP BY agrupa itens iguais na nossa tabela. è especificado normalmente quando queremos contar quantos itens temos iguais no banco de dados.Veja abaixo o exemplo que estou contando quantos nomes tenho repetido na nossa tabela 'teste'.

PS: Antes de executar eu alterei um dado com o seguinte sql:

UPDATE `teste` 
SET `USUARIO_NOME` = 'Usuario 3' 
WHERE `USUARIO_ID`=4;

Agora executamos o exemplo abaixo:

<?php
$stmt = $db->select ()
           ->from ( 'teste', array( 'USUARIO_NOME', 'COUNT(USUARIO_ID)' ) )
           ->group( 'USUARIO_NOME' )
           ->query ();
$result = $stmt->fetchAll ();

Veja que com a alteração agora temos dois itens com mesmo nome e o resultado tráz esta contagem.

Array
(
    [0] => Array
        (
            [USUARIO_NOME] => Usuario 1
            [COUNT(USUARIO_ID)] => 1
        )
    [1] => Array
        (
            [USUARIO_NOME] => Usuario 2
            [COUNT(USUARIO_ID)] => 1
        )
    [2] => Array
        (
            [USUARIO_NOME] => Usuario 3
            [COUNT(USUARIO_ID)] => 2
        )
)

Agora não esqueça de voltar ao valor antigo com o seguinte sql:

UPDATE `teste` 
SET `USUARIO_NOME` = 'Usuario 4' 
WHERE `USUARIO_ID` =4;

O DISTINCT

O parâmetro DISTINCT definimos quando não queremos dados repetidos na consulta. Para defini-lo utilizamos o método distinct() do Zend_Db_Select.

<?php
$stmt = $db->select ()
           ->distinct()
           ->from ( 'teste' )
           ->query ();
$result = $stmt->fetchAll ();

Fique por dentro de nossas novidades, ideias e atualizações