Añadiendo funciones SQL nativas a DQL en Symfony

DQL (Doctrine Query Language) soporta un conjunto limitado de funciones SQL específicas entre los diferentes sistemas gestores de base de datos (MySQL, PostgreSQL, Oracle o SQLite).

Una vez definido un proveedor de base de datos en nuestro proyecto (que en ningún caso cambiará en el futuro) podemos hacer uso de todas las funciones nativas disponibles.

Este artículo, muestra como añadir la función nativa DATE() de MySQL a Doctrine en un proyecto Symfony.

La función Date() extrae solo la fecha de una expresión de fecha y hora.

Primero se crea un fichero en src\AppBundle\DQL\DatetimeFunction\Date.php

<?php

namespace AppBundle\DQL\DatetimeFunction;

use Doctrine\ORM\Query\AST\Functions\FunctionNode;
use Doctrine\ORM\Query\Lexer;
use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\Query\SqlWalker;

class Date extends FunctionNode
{
    public $date;

    public function parse(Parser $parser)
    {
        $parser->match(Lexer::T_IDENTIFIER);
        $parser->match(Lexer::T_OPEN_PARENTHESIS);

        $this->date = $parser->ArithmeticPrimary();

        $parser->match(Lexer::T_CLOSE_PARENTHESIS);
    }

    public function getSql(SqlWalker $sqlWalker)
    {
        return "DATE(".$sqlWalker->walkArithmeticPrimary($this->date).")";
    }
}

A continuación, le indicamos a Symfony app/config/config.yml las nuevas funciones DQL añadidas de la siguiente manera:

doctrine: 
    orm: 
       dql: 
           datetime_functions:
               date: AppBundle\DQL\DatetimeFunction\Date
           
         
           #string_functions:
                #test: AppBundle\DQL\StringFunction\Test
           #numeric_functions:
                #test: AppBundle\DQL\NumericFunction\Test

DQL tiene 3 tipos de funciones, los que devuelven un valor numérico, una cadena y una fecha.

Por último, en nuestra consulta DQL src\AppBundle\Repository\ArticleRepository.php ya tenemos disponible la funcionalidad añadida.

public function findDate()
    {
        $now = new \DateTime('2016-04-28');

        return $this->createQueryBuilder('a')
            ->where('DATE(a.datetime) = :date')
            ->setParameter('date', $now)
            ->getQuery()
            ->execute();
    }

En este ejemplo, busco todas las fechas de tipo DateTime() de la entidad Article que sean iguales a fecha tipo Date() dada en la variable $now;

Recursos

Si te ha gustado éste artículo, te animo a compartirlo!😄

Articulo añadido a “A week of symfony”

Autor: Juan Luis García Borrego

Soy una persona responsable, activa, constante, con muchas ganas de aprender y crecer como profesional. Tengo un carácter positivo y agradable que me permite sentirme cómodo trabajando en equipo. Mis intereses profesionales se centran en torno a PHP, en concreto al framework Symfony y su ecosistema, en el cual me siento muy cómodo desarrollando y es un claro ejemplo de un software de calidad, con buenas prácticas y ‘Clean Code’.

2 opiniones en “Añadiendo funciones SQL nativas a DQL en Symfony”

  1. Ayer mismo tuve esa necesidad y me estuve planteando si hacerlo a la vieja usanza (creo datetime(fecha+”0:0:0″) y datetime(fecha+”23:59:59″) y hacer un between) o hacer algo más “nativo” (por ejemplo, como lo que has hecho).
    Al final, como soy tan “mijitas” opté por lo primero, por aquello de “abstracción total frente a la base de datos”.
    Pero tienes toda la razón en lo que has dicho de que sabemos a priori que la base de datos no va a cambiar y, ¿porqué no hacer algo más “nativo” en estos casos?
    Gracias por el artículo.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *