Symfony 2 : Extension doctrine pour créer ses propres fonctions DQL sur une plateforme.

De izzetali UNLU dans Technique

3 avr 2013

Objectif : Réussir à faire une requête insensible aux accents en DQL avec Doctrine 2.

Pour nous aider dans notre tâche nous avions trouvé un article très intéressant évoquant sur comment réussir une requête insensible aux accents sur ORACLE :

PgSQL
1
2
3
select prenom
from emp
where convert(prenom,'US7ASCII','WE8MSWIN1252') like '%heloise%' ;

Problématique rencontré : Lorsque nous avons voulu faire appel à la fonction CONVERT native de ORACLE via Doctrine 2 avec l’exemple ci-dessus, une erreur était générée car Doctrine 2 n’avait pas cette fonction définie dans son environnement

Code PHP impliqué :


public function rechercheByThemes($params){
try{
$qb = $this->_em->createQueryBuilder();
return $qb->select('t')
->from('PROJECTMYBundle:Theme', 't')
->where('t.supprime = 0 and (LOWER(CONVERT(t.libelle, :param1, :param2)) like LOWER(CONVERT(:texte, :param1, :param2)) or LOWER(CONVERT(t.memo, :param1, :param2)) like LOWER(CONVERT(:texte, :param1, :param2)))')
->setParameter('texte', '%'.$params['texte'].'%')
->setParameter('param1', 'US7ASCII')
->setParameter('param2', 'WE8MSWIN1252')
->getQuery()
->getArrayResult()
;
}
catch(\Doctrine\ORM\NoResultException $e){
return null;
}
}

Erreur PHP obtenue :
[Syntax Error] line 0, col 70: Error: Expected known function, got ‘CONVERT’

Solution : déclarer la fonction CONVERT native de ORACLE dans l’environnement de Doctrine 2.

Ensemble des fichiers qui seront modifiés dans l’environnement Doctrine 2 :
\vendor\doctrine\dbal\lib\Doctrine\DBAL\Platforms\OraclePlatform.php
\vendor\doctrine\orm\lib\Doctrine\ORM\Query\Parser.php

Nouveau fichier qui sera créé dans l’environnement Doctrine 2 :
\vendor\doctrine\orm\lib\Doctrine\ORM\Query\AST\Functions\ConvertFunction.php

Procédure :

  1. Nous déclarons dans la classe de la plateforme Oracle la nouvelle méthode CONVERT.
  2. Nous allons définir la nouvelle classe ConvertFunction qui va se charger d’implémenter la fonction CONVERT de ORACLE.
  3. Enfin nous rajoutons  dans la classe Parser le chemin de la fonction convert que nous avons défini dans la plateforme oracle.

1 – OraclePlatform.php  :
public function getConvertExpression($stringOne, $stringTwo, $stringThree)
 {
return 'CONVERT(' . $stringOne . ', ' . $stringTwo . ', ' . $stringThree .  ')';
}

2 – ConvertFunction.php :


namespace Doctrine\ORM\Query\AST\Functions;
use Doctrine\ORM\Query\Lexer;
class ConvertFunction extends FunctionNode
{

public $stringOne;
public $stringTwo;
public $stringThree;

public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
{
return $sqlWalker->getConnection()->getDatabasePlatform()->getConvertExpression(
$sqlWalker->walkSimpleArithmeticExpression($this->stringOne),
$sqlWalker->walkSimpleArithmeticExpression($this->stringTwo),

$sqlWalker->walkSimpleArithmeticExpression($this->stringThree)
);
}

public function parse(\Doctrine\ORM\Query\Parser $parser)
{

$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$this->stringOne = $parser->StringPrimary();
$parser->match(Lexer::T_COMMA);
$this->stringTwo = $parser->StringPrimary();
$parser->match(Lexer::T_COMMA);
$this->stringThree = $parser->StringPrimary();
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
}
}

Nous avons 2 méthodes dans cette classe :

  1. parse : cette méthode va parcourir le DQL et en extraire les parties souhaitées.
    1. Le parser reconnaît la fonction (Lexer :T_IDENTIFIER)
    2. Ouverture de la parenthèse (Lexer :T_OPEN_PARENTHESIS)
    3. Le parser lit la première expression et initialise stringOne avec cette valeur.
    4. Lecture de la virgule (Lexer :T_COMMA)
    5. Le parser lit la seconde expression et initialise stringTwo avec cette valeur
    6. Lecture de la virgule (Lexer :T_COMMA)
    7. Le parser lit la troisième expression et initialise stringThree avec cette valeur
    8. Fermeture de la parenthèse
    9. getSql : cette méthode se charge d’instancier la plateforme ($sqlWalker->getConnection()->getDatabasePlatform()) pour utiliser la méthode getConvertExpression que nous avons créée.

3 – Parser.php :
private static $_STRING_FUNCTIONS = array(

'convert'     => 'Doctrine\ORM\Query\AST\Functions\ConvertFunction',

);

Commentaire

+ neuf = 15

iMDEO recrute !

REJOIGNEZ-NOUS

A la recherche de nouveaux talents (développeurs web et mobile, chefs de projet,...)

Voir les annonces