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