Capítulo 3. Zend_Db

Índice

3.1. Zend_Db_Select
3.1.1. Introdução
3.1.2. Colunas de uma Tabela (usando FROM)
3.1.3. Colunas de Tabelas (usando JOIN)
3.1.4. Condições WHERE
3.1.5. Cláusula GROUP BY
3.1.6. Condição HAVING
3.1.7. Cláusula ORDER BY
3.1.8. LIMIT usando Count e Offset
3.1.9. LIMIT usando Page e Count
3.2. Zend_Db_Select
3.2.1. Introdução
3.2.2. Colunas de uma Tabela (usando FROM)
3.2.3. Colunas de Tabelas (usando JOIN)
3.2.4. Condições WHERE
3.2.5. Cláusula GROUP BY
3.2.6. Condição HAVING
3.2.7. Cláusula ORDER BY
3.2.8. LIMIT usando Count e Offset
3.2.9. LIMIT usando Page e Count
3.3. Zend_Db_Table
3.3.1. Introdução
3.3.2. Iniciando
3.3.3. Nome da Tabela e Chave Primária
3.3.4. Inserindo Linhas
3.3.5. Atualizando Linhas
3.3.6. Apagando Linhas
3.3.7. Encontrando Linhas por Chave Primária
3.3.8. Buscando Uma Linha
3.3.9. Buscando Múltiplas Linhas
3.3.10. Incluindo Lógica de Domínio
3.4. Zend_Db_Table_Row
3.4.1. Introdução
3.4.2. Buscando uma Linha
3.4.3. Modificando Valores
3.5. Zend_Db_Table_Rowset
3.5.1. Introdução
3.5.2. Buscando um Rowset
3.5.3. Percorrendo o Rowset

3.1. Zend_Db_Select

3.1.1. Introdução

Zend_Db_Select é uma ferramenta para construir instruções SQL SELECT independentemente do banco de dados utilizado. Obviamente isso não pode ser perfeito, mas é um avanço para ajudar a fazer consultas portáveis entre banco de dados diferentes. Adicionalmente, ele ajuda a proteger suas consultas contra ataques de SQL injection.

A maneira mais fácil de criar uma instância de Zend_Db_Select é usar o método Zend_Db_Adapter::select().

<?php
	
require_once 'Zend/Db.php';

$params = array (
    'host'     => '127.0.0.1',
    'username' => 'malory',
    'password' => '******',
    'dbname'   => 'camelot'
);

$db = Zend_Db::factory('pdoMysql', $params);

$select = $db->select();
// $select é agora um objeto Zend_Db_Select_PdoMysql

?>

Então você constrói uma consulta SELECT usando o objeto e seus métodos, e em seguida gera uma string para devolver ao Zend_Db_Adapter para consultas ou buscas.

<?php
	
//
// SELECT *
//     FROM round_table
//     WHERE noble_title = "Sir"
//     ORDER BY first_name
//     LIMIT 10 OFFSET 20
//

// você pode usar um estilo iterativo...
$select->from('round_table', '*');
$select->where('noble_title = ?', 'Sir');
$select->order('first_name');
$select->limit(10,20);

// ...ou um estilo "fluente":
$select->from('round_table', '*')
       ->where('noble_title = ?', 'Sir')
       ->order('first_name')
       ->limit(10,20);

// de um modo ou de outro, busque os resultados
$sql = $select->__toString();
$result = $db->fetchAll($sql);

// alternativamente, você pode passar o objeto $select;
// Zend_Db_Adapter é esperto o suficiente para chamar __toString() nos
// objetos Zend_Db_Select para pegar a string de consulta.
$result = $db->fetchAll($select);

?>

Você também pode usar parâmetros vinculados nas suas consultas em vez de adicionar aspas a cada método.

<?php
	
//
// SELECT *
//     FROM round_table
//     WHERE noble_title = "Sir"
//     ORDER BY first_name
//     LIMIT 10 OFFSET 20
//

$select->from('round_table', '*')
       ->where('noble_title = :title')
       ->order('first_name')
       ->limit(10,20);

// de um modo ou de outro, busque os resultados usando os parãmetros vinculados
$params = array('title' => 'Sir');
$result = $db->fetchAll($select, $params);

?>

3.1.2. Colunas de uma Tabela (usando FROM)

Para selecionar colunas de uma tabela específica, use o método from(), specificando a tabela e as colunas que você quer. Você pode usar apelidos para a tabela e para colunas, e você pode usar from() quantas vezes precisar.

<?php
	
// crie um objeto $db, usando Mysql como o adaptador.
$select = $db->select();

// SELECT a, b, c FROM some_table
$select->from('some_table', 'a, b, c');
// equivalente:
$select->from('some_table', array('a', 'b', 'c');

// SELECT bar.col FROM foo AS bar
$select->from('foo AS bar', 'bar.col');

// SELECT foo.col AS col1, bar.col AS col2 FROM foo, bar
$select->from('foo', 'foo.col AS col1');
$select->from('bar', 'bar.col AS col2');

?>

3.1.3. Colunas de Tabelas (usando JOIN)

Para selecionar colunas usando tabelas unidas, use o método join(). Primeiro passe o nome da tabela que se unirá, então a condição da união, e finalmente as colunas que você quer unir. Você pode usar join() quantas vezes precisar.

<?php
	
// crie um objeto $db, usando Mysql como adaptador.
$select = $db->select();

//
// SELECT foo.*, bar.*
//     FROM foo
//     JOIN bar ON foo.id = bar.id
//
$select->from('foo', '*');
$select->join('bar', 'foo.id = bar.id', '*');

?>

No momento, apenas a sintaxe de JOIN é suportada; não LEFT JOINs, RIGHT JOINs, etc. Versões futuras vão suportar estas operações de um modo independente de bancos de dados.

3.1.4. Condições WHERE

Para adicionar condições WHERE, use o método where(). Você pode passar uma string regular, ou uma string com um ponto de interrogação marcando um espaço reservado e um valor para adicionar aspas nela (o valor receberá aspas usando Zend_Db_Adapter::quoteInto).

Chamadas múltiplas a where() adicionarão AND às condições; se você precisar de OR, use orWhere().

<?php
	
// crie um objeto $db, e pega a ferramenta SELECT.
$select = $db->select();

//
// SELECT *
//     FROM round_table
//     WHERE noble_title = "Sir"
//     AND favorite_color = "yellow"
//
$select->from('round_table', '*');
$select->where('noble_title = "Sir"'); // embedded value
$select->where('favorite_color = ?', 'yellow'); // quoted value

//
// SELECT *
//     FROM foo
//     WHERE bar = "baz"
//     OR id IN("1", "2", "3")
//
$select->from('foo', '*');
$select->where('bar = ?', 'baz');
$select->orWhere('id IN(?)', array(1, 2, 3);

?>

3.1.5. Cláusula GROUP BY

Para agrupar linhas, use o método group() quantas vezes você desejar.

<?php
	
// crie um objeto $db, e pega a ferramenta SELECT.
$select = $db->select();

//
// SELECT COUNT(id)
//     FROM foo
//     GROUP BY bar, baz
//
$select->from('foo', 'COUNT(id)');
$select->group('bar');
$select->group('baz');

// chamada equivalente de group():
$select->group('bar, baz');

// outra chamada equivalente de group():
$select->group(array('bar', 'baz'));

?>

3.1.6. Condição HAVING

Para adicionar condições HAVING aos resultados selecionados, use o método having(). este método é id~entico em função ao método where().

Se você chamar having() múltiplas vezes, as condições são unidas usando AND; se você quiser uma condição OR, use orHaving().

<?php
	
// crie um objeto $db, e pega a ferramenta SELECT.
$select = $db->select();

//
// SELECT COUNT(id) AS count_id
//     FROM foo
//     GROUP BY bar, baz
//     HAVING count_id > "1"
//
$select->from('foo', 'COUNT(id) AS count_id');
$select->group('bar, baz');
$select->having('count_id > ?', 1);

?>

3.1.7. Cláusula ORDER BY

Para ordenar colunas com ORDER, use o método order() quantas vezes desejar.

<?php
	
// crie um objeto $db, e pega a ferramenta SELECT.
$select = $db->select();

//
// SELECT * FROM round_table
//     ORDER BY noble_title DESC, first_name ASC
//
$select->from('round_table', '*');
$select->order('noble_title DESC');
$select->order('first_name');

// chamada equivalente de order():
$select->order('noble_title DESC, first_name');

// outra chamada equivalente de order():
$select->order(array('noble_title DESC', 'first_name'));

?>

3.1.8. LIMIT usando Count e Offset

Zend_Db_Select oferece abstrações pra suporte da cláusula LIMIT. Para muitos bancos de dados, como MySQL e PostgreSQL, isso é relativamente fácil, pois eles suportam a sintaxe "LIMIT :count [OFFSET :offset]".

Para outros bancos de dados, como Microsoft SQL e Oracle, isso não é tão fácil, pois eles não suportam cláusulas LIMIT. MS-SQL tem apenas uma cláusula TOP, e Oracle requer que a consulta seja escrita de uma maneira especial para emular um LIMIT. Devido à maneira como o Zend_Db_Select trabalhar internamente, nós podemos reescrever SELECT para emular a funcionalidade LIMIT dos bancos de dados de código aberto mencionados anteriormente.

Para usar LIMIT nos resultados retornados usando count e offset, use o método limit() com um valor count e um offset opcional.

<?php
	
// primeiro, um simples "LIMIT :count"
$select = $db->select();
$select->from('foo', '*');
$select->order('id');
$select->limit(10);

//
// Em MySQL/PostgreSQL/SQLite, isso se traduz para:
//
// SELECT * FROM foo
//     ORDER BY id ASC
//     LIMIT 10
//
// Mas em Microsoft SQL, isso se traduz para:
//
// SELECT TOP 10 * FROM FOO
//     ORDER BY id ASC
//
//

// agora, um mais complexo "LIMIT :count OFFSET :offset"
$select = $db->select();
$select->from('foo', '*');
$select->order('id');
$select->limit(10, 20);

//
// Em MySQL/PostgreSQL/SQLite, isso se traduz para:
//
// SELECT * FROM foo
//     ORDER BY id ASC
//     LIMIT 10 OFFSET 20
//
// Mas em Microsoft SQL, que não tem suporte a offset, isso se traduz para
// algo como:
//
// SELECT * FROM (
//     SELECT TOP 10 * FROM (
//         SELECT TOP 30 * FROM foo ORDER BY id DESC
//     ) ORDER BY id ASC
// )
//
// Zend_Db_Adapter faz a tradução da consulta automaticamente.
//

?>

3.1.9. LIMIT usando Page e Count

Zend_Db_Select também oferece limites baseados em páginas. Se você quer receber uma certa "página" de resultados, use o método limitPage(); primeiro passe o número da página que voc~e quer, e então o número de linhas que aparecerão em cada página.

<?php
	
// construa o select básico...
$select = $db->select();
$select->from('foo', '*');
$select->order('id');

// ... e limite o resultado à página 3, cada página com 10 linhas
$select->limitPage(3, 10);

//
// Em MySQL/PostgreSQL/SQLite, isso se traduz para:
//
// SELECT * FROM foo
//     ORDER BY id ASC
//     LIMIT 10 OFFSET 20
//

?>