lunes, 7 de abril de 2008

Zend_Db_Select




Con esta clase nosotros vamos a poder generar nuestras querys. Agregar todas las cláusulas que consideremos necesarias, de forma ordenada, y obteniendo algunas ventajas con respecto a la manera tradicional.

Hay dos formas de acceder a esta clase usando el método directamente de la clase abstracta Zend_Db_Adapter_Abstract

Ejemplo:

1  
<?php
2  $db 
Zend_Db::factory(...opciones...);
3  
$select $db->select();
4  
?>



O especificando el adaptador de la base de datos.

Ejemplo:

1  
<?php
2  $db 
Zend_Db::factory(...opciones...);
3  
$select = new Zend_Db_Select($db);
4  
?>



Nosotros una vez creado la instancia de Zend_Db_Select, podemos ir agregando tantas cláusulas como necesitemos.

1  
<?php
2  $select
->select();
3  
$select->from'tabla' );
4  
$select->where' id=1 ' );
5  
$select->order'nombre' );
6  
?>



Y de esta manera vamos a crear una query con la siguiente forma

SELECT * FROM tabla WHERE id=1 ORDER BY nombre

Nosotros podríamos optimizar este código usando interfaces fluidas.

Las interfaces fluidas tienen un método principal ( select() ), que va a recibir los mensajes de los métodos posteriores.

Si nuestro código anterior lo generamos usando interfaces fluidas nos quedaría de la siguiente forma.


1  
<?php
2  $select
->select()
3  ->
from'tabla' )
4  ->
where' id=1 ' )
5  ->
order'nombre' );
6  
?>



hay casos donde no nos va a convenir usar la forma de interfaz fluida y vamos a usar la forma "no fluida", y eso será cuando tengamos que validar algo antes, o ejecutar algo entre métodos.

Cláusula FROM

A veces necesitamos crear un alias a la tabla, un string que identifique a la tabla dentro de nuestra Query. Para hacerlo nosotros vamos a enviar los parámetros a from(), en forma de array.

Por ejemplo para decir que la tabla usuarios tiene el alias us.

1  
<?php
2  $query 
$db->select()
3  ->
from( array('us' => 'usuarios') );
4  
?>



De esta manera nuestro select nos va a quedar de la siguiente forma

SELECT * FROM usuarios As us

Si nosotros al método from() no le especificamos que columna queremos que nos traiga, nos va a traer todas ( * ), pero si queremos especificar esto, vamos a enviarle los campos que queremos que nos muestre en un array, como segundo parámetro del from();

por ejemplo:

Si quisiéramos decirle al query, que nos devuelva solo el id, y el nombre del registro, tendríamos que crear el siguiente código

1  
<?php
2  $select 
$db->select()
3  ->
from(array('us' => 'usuarios'),
4  array(
'id_usuario''nombre_usuario'));
5  
?>



O si a esos campos los tenemos que relacionar con el alias de la tabla nos quedaría de la siguiente forma

1  
<?php
2  $select 
$db->select()
3  ->
from(array('us' => 'usuarios'),
4  array(
'us.id_usuario''us.nombre_usuario'));
5  
?>



O si además queremos agregarle alias a nuestros campos podemos hacerlo de la misma forma que lo hacíamos con la tabla

1  
<?php
2  $select 
$db->select()
3  ->
from(array('us' => 'usuarios'),
4  array(
'id'=>'us.id_usuario''nombre'=>'us.nombre_usuario'));
5  
?>



Agregando más tablas a la consulta

Muchas veces necesitamos relacionar tablas usando los famosos JOIN, para hacerlo con Zend es realmente fácil, como todo con Zend

Si quisiéramos listar la cantidad de productos relacionado con un proveedor, la consulta tendría que ser así

1  
<?php
2  $select 
$db->select()
3  ->
from(array('p1'=>'productos')
4  ->
join(array('p2'=>'proveedores'),' p2.id_proveedor = p1.id_proveedor');
5  
?>



En el primer parámetro del join ingresamos la tabla a relacionar, y en el segundo parámetro la condición para relacionar esta tabla con la primera.

Existe un tercer parámetro y son la cantidad de columnas de la tabla que queremos listar y enviamos estos campos en una tabla de la misma forma que lo usamos en el from().

Inner Join método: join() joinInner().

Left Join método: joinLeft().

Rigth Join método: joinRight().

Full Join método joinFull().

Hay dos casos que no reciben los parámetros de la misma manera, son Cross Join, y Natural Join. Estos reciben en el primer parámetro la tabla, y en el segundo las columnas a listar.

Cross Join método: joinCross().

Natural Join método: joinNatural().

La cláusula WHERE.

La cláusula WHERE recibe dos parámetros el primero es la condición explicita, por ejemplo

1  
<?php
2  $select 
$db->select()
3  ->
from('productos')
4  ->
where'estado = 1' );
5  
?>



El segundo parámetro es una variable para el valor que puede estar ocultado por un símbolo de pregunta (?), esto se usa para usar como variable.

por ejemplo

1  
<?php
2  $estado 
1;
3  
$select $db->select()
4  ->
from('productos')
5  ->
where'estado = ?'$estado )
6  
?>



El segundo parámetro va a reemplazar en la consulta al símbolo '?'.

Si nosotros quisiéramos agregar mas de una condición, tenemos dos opciones, en el primer parámetro agregar al string un AND u OR otra condición, o agregar otra llamada al método where()

por ejemplo

1  
<?php
2  $hoy 
date("Y-m-d");
3  
$estado 1;
4  
$select $db->select()
5  ->
from('productos')
6  ->
where'estado = ?'$estado )
7  ->
where'fecha < ?'$hoy);
8  
?>



cada vez que agregamos un where(), el sistema lo transforma en un AND condición, si nosotros quisiéramos agregar una condición y que esta condición sea un OR, tendríamos que usar el método orWhere(), con las mismas características que el where().

por ejemplo

1  
<?php
2  $hoy 
date("Y-m-d");
3  
$estado 1;
4  
$select $db->select()
5  ->
from('productos')
6  ->
where'estado = ?'$estado )
7  ->
orWhere'fecha < ?'$hoy);
8  
?>



Cláusula GROUP BY.

tendríamos que agregar tantos group(), como agrupamientos queramos por ejemplo

1  
<?php
2  $select 
$db->select()
3  ->
from'productos' )
4  ->
group'fecha' )
5  
?>



Cláusula HAVING.

Agregamos al select(), el método having, con la expresión que queramos. Por ejemplo

1  
<?php
2  $select 
$db->select()
3  ->
from'productos', array( ‘precio’ )
4  ->
group'fecha' )
5  ->
having‘precio 35’ )
6  
?>



También existe el método orHaving(), para que puedan agregar a la consulta.

Cláusula ORDER

Si nosotros queremos que los registros se ordenen por una o mas columnas tenemos que usar el método order() dentro de nuestro select().

Si nosotros quisiéramos ordenar primero en forma Descendente por precio, y despues en forma ascendente por Nombre, tendríamos el siguiente código.

1  
<?php
2  $select 
$db->select()
3  ->
from'productos', array( ‘precio’ )
4  ->
order(array( ‘precio DESC’‘nombre’ ));
5  
?>



Cláusula LIMIT

Si quisiéramos limitar la cantidad de registros vamos a usar el método limit(). Esta cláusula esta compuesto de dos parámetros, desde y cuantos. Si nosotros quisiéramos que nos traiga los primeros 10 registros tendríamos que decirle limit(1,10).

Otro ejemplo seria si necesitamos que nos traiga 10 registros a partir del registro 20, tendríamos que usar limit(20,10).

1  
<?php
2  $select 
$db->select()
3  ->
from'productos' )
4  ->
limit(20,10);
5  
?>



además nosotros tenemos la posibilidad de usar pageLimit(), que también consta de dos parámetros.

Cláusula DISTINCT

Solo distinct(), sin ningún parámetro por ejemplo

1  
<?php
2  $select 
$db->select()
3  ->
distinct()
4  ->
from'productos' )
5  
?>



Cláusula FOR UPDATE

Al igual que distinct(), no lleva parámetros

1  
<?php
2  $select 
$db->select()
3  ->
forUpdate()
4  ->
from'productos' )
5  
?>



Estas son todas los métodos que necesitamos para armar nuestros Quero.

Para ejecutarlos vamos a usar query(), y para mostrar todos los registros fetchaAll().

1  
<?php
2  $select 
$db->select()
3  ->
from‘productos’ );
4  
$sql $db->query($select);
5  
$rows $sql->fetchAll();
6  
?>



Todo lo que tenga que ver con Base de datos siempre tenemos que ubicarlo dentro de nuestro modelo, no dentro del controlador o de la vista, siempre en el modelo.

Fuente Zend_Db_Select
Gracias Santiago por la definicion de Fluent Interface ;)

5 comentarios:

Milo dijo...

Interfaces fluidas no es un concepto Pablo...
salu2

Pablo Morales dijo...

Nadie dijo que lo era ;)

Fede? dijo...

COmo andás con las traducciones titán, ya tenes doscientas mil visitas diarias, una locura.

Acido 69 dijo...

hola pablo; buena la traducción.
creo que se te han pasado unos punto y coma(;) en los ejemplos de "Where"
...
->where('', '');
->where('', '');
...

Pablo Morales dijo...

Ya lo arregle gracias acido