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



April 7th, 2008 at 11:24 am
Interfaces fluidas no es un concepto Pablo…
salu2
April 7th, 2008 at 11:27 am
Nadie dijo que lo era
April 9th, 2008 at 3:41 pm
COmo andás con las traducciones titán, ya tenes doscientas mil visitas diarias, una locura.
April 22nd, 2008 at 3:59 pm
hola pablo; buena la traducción.
creo que se te han pasado unos punto y coma(;) en los ejemplos de “Where”
…
->where(”, ”);
->where(”, ”);
…
April 23rd, 2008 at 5:13 am
Ya lo arregle gracias acido
September 9th, 2008 at 11:28 pm
Hola Pablo, buen articulo, ahora tengo una duda, si quiero crear una Clase, para hacer mis consultas, tengo que extenderla a Zend_Db_Adapter_Abstract, o no la extiendo??
September 9th, 2008 at 11:56 pm
Claro.
class Productos extends Zend_Db_Table_Abstract
{
protected $_name = “productos”;
public function findAll()
{
$this->fetchAll( $this->select()->where( ‘estado = 0′ ));
}
}
September 9th, 2008 at 11:58 pm
Ahora si voy entendiendo, una preguntita mas, si voy a utilizar INNER JOIN, debo agregar por ejemplo las tablas que participan con
protected $_name = “tabla_2”;
protected $_name = “tabla_3”;
Es asi?
Un abrazo
September 10th, 2008 at 12:49 am
No. Cada modelo representa una tabla de tu sistema, en teoria.
Puede ser que no necesites crear un modelo para una tabla, o puede ser que no necesites una tabla para un modelo.
Si vos tenes que hacer un inner join, con Zend_Db_Select. Tenes que agregar el nombre de la tabla. Con la que queres joinear (no existe este verbo, lo acabo de inventar).
pero te podes evitar el hecho de agregar el from
$this->select()->join(array(’p'=>’proveedores’))
se entiende?
September 10th, 2008 at 12:59 am
intento entenderlo, pero por ejemplo, si quiero crear una clase, la cual sus metodos me hacen consultas tipo
$this->select()->join(array(’p’=>’proveedores’))
esa clase, tengo que extenderla?, creo que no hace falta, que dicha clase no es un modelo.
Es asi?
September 10th, 2008 at 1:18 am
Creo que te estas confundiendo.
Si tenes una clase que no es un modelo, o una funcion, o directamente un codigo suelto por ahi, no existe la necesidad, pero si vas a tener que que instanciar la clase Zend_Db, como esta en este articulo.
En el proximo post, voy a hacer una conexion a la base de datos, y un modelo de ejemplo, por ahi eso te ayude a entenderlo mejor.
Saludos.
September 10th, 2008 at 8:18 am
dale, buenisimo, lo voy a estar esperando. Creo que todavia confundo, modelo, con una clase convencional, y cual es la ventaja de usar “un modelo”.
Un abrazo.
September 10th, 2008 at 9:09 am
Es una capa mas
Que en este caso el modelo se encarga de la logica de negocio.
December 7th, 2008 at 6:01 am
Yo prefiero utilizar Zend_Db_Table.
Lo que pasa es que Zend_Db_Table no soporta Join.
Hay que utilizar unos trucos para poder hacer join entre varias tablas. Utilizo una clase modifica para ZF 1.5.x y >
de esta web :
http://www.assembla.com/spaces/riskle/documents
Y desde poco utilizo vista MySQL 5.
La ultima solución creo que la mejor pero lo que pasa es no muy practico gestionar las “vistas” con phpMyAdmin. Mejor utilizar programas como Navicat o algo así.
Si le interesa alguien le puede mandar estas clases.
December 8th, 2008 at 12:39 am
Hola Sebastien. Te cuento que Zend_Db_Table usa un patron que se llama Gateway, no soy un experto pero te puedo decir que la idea es que vos solo pidas datos de TU tabla y no de otras, si vos queres traer datos de otras tablas ahi vas a estar en problemas porque rompes con el patron, lo mas politicamente correcto es hacer el join desde el controller, o desde algun helper.
Por otro lado, si vos queres traer los datos de TU tabla, y los joins, solo lo usas para filtrar, ahi es otro cantar, a partir de la version 1.5.x con solo llamar a setIntegrity(false), es suficiente para que te deje joinear, pero No podes traer dato de otras tablas simplemente porque rompe con el patron.
December 8th, 2008 at 9:42 am
Totalmente deacuerdo. Efectivamente Zend_Db_Table responde al pattern gateway por eso utilizo Mysql View así en realidad hago el join directamente en Mysql. La clase de Riskle es practica en caso de no poder hacer view. Es verdad que rompe el eschema pera a veces es utí para no sobrecargar el controller.
December 8th, 2008 at 9:57 am
Ahhh ahora te entiendo mas, vos estas creando una vista y despues haces un modelo para esa vista, no?
Tambien podes usar Zend_Db_Table_Relationships, para crear un modelo que se relacione con otros. Aca tenes un link de como usarlo
http://bolsadeideas.cl/zsamer/2008/08/implementar-orm-en-zend-framework-db-table/
En mi trabajo actual estamos usando varios ejemplos con este sistema, y anda bastante bien.