Introducción
Las aplicaciones en Symfony 2 no acceden directamente a la base de datos, sino que utilizan objetos PHP para acceder a los datos, sin ejecutar directamente las sentencias SQL. Para realizar este trabajo utiliza la librería Doctrine por defecto, aunque también se pueden utilizar otras como Propel.
La forma más habitual es realizar la obtención de datos mediante DQL, con la cual obtendremos los datos como objetos PHP listos para su utilización. En el libro The Book for Symfony 2.0 [1] se puede ver una introducción a esta forma de obtener los datos, supongo que se tiene conocimiento en el uso de DQL. En ocasiones nos puede interesar añadir en el repositorio de una entidad una consulta que no nos devuelva un objeto sino datos directamente.
Ejemplos de Consultas
Lo primero que podemos necesitar es obtener el numero de objetos que cumplen cierta condición, pero queremos hacer algo más eficaz que leer todos los objetos y contarlos después. Doctrine nos propocina getSingleScalarResult() es un atajo de getResult(Query::HYDRATE_SINGLE_SCALAR). La forma de uso es muy sencilla como se puede ver:
public function countUserInvoices($customer_id){
return $this->getEntityManager()
->createQuery('SELECT count(i.id)
FROM TestProgram:Invoice i
WHERE i.customer_id = :idCustomer')
->setParameter('idCustomer',$customer_id)
->getSingleScalarResult();
}
Con este ejemplo podemos ver como obtener el número de facturas de un determinado cliente. Se utiliza DQL, pero con el método getSingleScalarResult nos devolverá el número, no el objeto.
Esta forma de obtener datos puede ser útil para obtener ciertos datos, pero tal vez para otros sientas la necesidad de algo mas, poder lanzar la sentencia SQL que tu quieres, pero siguiendo utilizando el entorno que nos proporciona Symfony 2 y Doctrine. Para ello debemos utilizar ResultSetMapping como vemos en el manual de Doctrien [2].Veamos un ejemplo:
public function findStadisticsYear($costumer_id, $year){
$rsm = new \Doctrine\ORM\Query\ResultSetMapping();
$rsm->addScalarResult('month', 'month');
$rsm->addScalarResult('num_invoices', 'num_invoices');
$rsm->addScalarResult('total_amount', 'total_amount');
$q = $this->getEntityManager()->createNativeQuery(
'SELECT MONTH(i.date) as month,
count(i.id) as num_invoices,
sum(i.amount) as total_amount
FROM invoice
WHERE costumer_id=:idCostumer
AND YEAR(i.date) = :year
GROUP BY MONTH(i.date) ',
$rsm);
$q->setParameter('idCostumer', $costumer_id)
->setParameter('year', $year);
return $q->getResult();
}
Como podemos observar en esta ocasión no utilizamos DQL sino directamente una SQL con los nombres y campos de la tabla de la base de datos, no con el nombre de la clase y las propiedades de esta. Nos devolverá una matriz con tantos registros como meses con facturas tenga el cliente. Cada registro será un vector, al que podemos acceder a los datos mediante el nombre de la columna, de la seguiente forma data['total_amount']
Bibliografia
[1] 2012-06-20 "The Book for Symfony 2.0" pag.89 http://http://symfony.com/[2] 2010-02-10 "Guide to Doctrine for PHP" pag.85 http:///www.doctrine-project.org
0 comentarios:
Publicar un comentario