Symfony 2 et Doctrine: comment ajouter les fonctions spécifiques MySQL

Imaginons que vous fassiez un Repository dans lequel vous essayez d’éxecuter une fonction ainsi :

    <?php
    public function findNearest(...) {
        return $this->createQueryBuilder('p')
            ->select(array(
                'p.id',
                'COS(5) as distance'
            ))
            ->having('distance>:dmin')
            ->addOrderBy('distance', 'DESC')
            ->setParameters(array(
                'dmin' => $distance_min,
            ));
    }

Alors vous verrez que Doctrine ne connait pas la fonction cosinus COS().
Vous aurez l’erreur :

[Syntax Error] line 0, col 27: Error: Expected known function, got 'COS'

Doctrine ne connait pas la fonction cosinus COS(), mais aussi plein d’autres fonctions.

Pour les avoir disponibles, il faut aller les chercher sur github, ici.

Ici, vous pourrez récupérer toutes ces fonctions : DateAdd(), Sha1(), NullIf(), Field(), Month(), Sin(), MatchAgainst(), Acos(), Day(), CountIf(), GroupConcat(), Radians(), TimestampDiff(), ConcatWs(), Cot(), IfElse(), FindInSet(), IfNull(), Cos(), Asin(), Md5(), Year(), Sha2(), Week(), CharLength(), DateDiff(), StrToDate(), Atan(), Tan(), Atan2() et Degrees()

Ensuite, comme je ne voulais pas tous les fichiers, mais que les extensions, je les ai toutes mises dans mon répertoire dédié : src/HQF/Bundle/PizzasBundle/DQL/MySQL/.
Puis j’ai modifié à la main tous les fichiers en les déclarant dans le namespace adéquat (namespace HQF\Bundle\PizzasBundle\DQL\MySQL;).

Une fois cela fait, j’ai ajouté les déclarations de ces fonctions dans le fichier de config général app/config/config.yml. La petite astuce très importante et qui m’a fait perdre un temps fou (et c’est pour ça que je fait cet article en fait), qui n’est pas très claire dans la documentation : le nom qu’on déclare doit correspondre au texte qu’on trouve dans la fonction. Donc, dans le fichier, on a [nom de la fonction]:[classe] :

J’essayais de déclarer mafonction_acos: HQF\Bundle\PizzasBundle\DQL\MySQL\Acos et ça ne fonctionnait pas. Il fallait donner le nom de la fonction : acos: HQF\Bundle\PizzasBundle\DQL\MySQL\Acos

doctrine:
    ...blabla...
    orm:
        default_entity_manager: default
        entity_managers:
            default:
                connection: default
                ...blabla...
                dql:
                    numeric_functions:
                        acos: HQF\Bundle\PizzasBundle\DQL\MySQL\Acos
                        asin: HQF\Bundle\PizzasBundle\DQL\MySQL\Asin
                        atan2: HQF\Bundle\PizzasBundle\DQL\MySQL\Atan2
                        atan: HQF\Bundle\PizzasBundle\DQL\MySQL\Atan
                        charlength: HQF\Bundle\PizzasBundle\DQL\MySQL\CharLength
                        concatws: HQF\Bundle\PizzasBundle\DQL\MySQL\ConcatWs
                        cos: HQF\Bundle\PizzasBundle\DQL\MySQL\Cos
                        cot: HQF\Bundle\PizzasBundle\DQL\MySQL\Cot
                        countif: HQF\Bundle\PizzasBundle\DQL\MySQL\CountIf
                        dateadd: HQF\Bundle\PizzasBundle\DQL\MySQL\DateAdd
                        datediff: HQF\Bundle\PizzasBundle\DQL\MySQL\DateDiff
                        day: HQF\Bundle\PizzasBundle\DQL\MySQL\Day
                        degrees: HQF\Bundle\PizzasBundle\DQL\MySQL\Degrees
                        field: HQF\Bundle\PizzasBundle\DQL\MySQL\Field
                        findinset: HQF\Bundle\PizzasBundle\DQL\MySQL\FindInSet
                        groupconcat: HQF\Bundle\PizzasBundle\DQL\MySQL\GroupConcat
                        ifelse: HQF\Bundle\PizzasBundle\DQL\MySQL\IfElse
                        ifnull: HQF\Bundle\PizzasBundle\DQL\MySQL\IfNull
                        matchagainst: HQF\Bundle\PizzasBundle\DQL\MySQL\MatchAgainst
                        md5: HQF\Bundle\PizzasBundle\DQL\MySQL\Md5
                        month: HQF\Bundle\PizzasBundle\DQL\MySQL\Month
                        nullif: HQF\Bundle\PizzasBundle\DQL\MySQL\NullIf
                        radians: HQF\Bundle\PizzasBundle\DQL\MySQL\Radians
                        sha1: HQF\Bundle\PizzasBundle\DQL\MySQL\Sha1
                        sha2: HQF\Bundle\PizzasBundle\DQL\MySQL\Sha2
                        sin: HQF\Bundle\PizzasBundle\DQL\MySQL\Sin
                        strtodate: HQF\Bundle\PizzasBundle\DQL\MySQL\StrToDate
                        tan: HQF\Bundle\PizzasBundle\DQL\MySQL\Tan
                        timestampdiff: HQF\Bundle\PizzasBundle\DQL\MySQL\TimestampDiff
                        week: HQF\Bundle\PizzasBundle\DQL\MySQL\Week
                        year: HQF\Bundle\PizzasBundle\DQL\MySQL\Year

6 comments

  1. Ping : Symfony 2 : avantages et inconvénients | Olivier Pons

Poster un commentaire

Vous devriez utiliser le HTML:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.