/* 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.
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 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 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 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 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 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 ();