Bonjour,

Je suis confronté au problème suivant : je souhaiterai remplacer le comportement de la fonction IF() MySQL par une gestion de celui-ci via Doctrine, cela pour des raisons de portabilité.

Concrètement, je veux supprimer l'utilisation de la fonction MySQL "IF(champ1 IS NOT NULL, champ1, champ2) AS champFinal" dans ma requête.

Pour le moment, j'ai trouvé la solution suivante : ajouter les 2 champs dans la requête pour les obtenir dans le résultat fourni par PDO, puis utiliser un listener d'hydratation en preHydrate, afin d'effectuer le test sur les deux champs à ce niveau, et ainsi d'ajouter le champ final dans la liste des champs à hydrater.


Voici le code (regroupé dans un seul fichier pour l'exemple) :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
 
/**
   * Modèle de table "adhérents".
   */
class AdherentsTable extends Doctrine_Table
{
        public function myFunction()
	{
		$q = $this->createQuery('a')->select('a.id,
    								   a.champ1,
								   a.champ2');
 
                return $q->execute(array(), Doctrine_Core::HYDRATE_SCALAR);
        }
 
        /**
           * Ajouter le listener d'hydratation.
           */
        public function construct()
	{
		$this->addRecordListener(new HydrationListener());
	}
}
 
/**
   * HydrationListener pour AdherentsTable.
   */
class HydrationListener extends Doctrine_Record_Listener
{
    public function preHydrate(Doctrine_Event $event)
    {
        $data = $event->data;
        $data['champFinal'] = null;
 
        if (isset($data['champ1']) && !empty($data['champ1'])) : 
        	$data['champFinal'] = $data['champ1'];
        elseif (isset($data['champ2'])) :
        	$data['champFinal'] = $data['champ2'];
        endif;
 
        $event->data = $data;
    }
}
 
//Main
var_dump(Doctrine_Core::getTable('Adherents')->myFunction());

Le résultat suivant est retourné :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
 
array(1) {
  [0] => array(11) {
    ["a_id"] => string(1) "2"
    ["a_champ1"] => string(14) "valeur champ 1"
    ["a_champ2"] => string(14) "valeur champ 2"
  }
}
Le listener n'est donc pas appelé en mode d'hydratation scalaire.
Par contre, si jamais je choisis le mode d'hydratation array (Doctrine_Core::HYDRATE_ARRAY), le listener est bien appelé, et je récupère bien mon nouveau champ :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
 
array(1) {
  [0] => array(11) {
    ["a_id"] => string(1) "2"
    ["a_champ1"] => string(14) "valeur champ 1"
    ["a_champ2"] => string(14) "valeur champ 2"
    ["a_champFinal"] => string(14) "valeur champ 1"
  }
}

En me plongeant dans le code de Doctrine, j'ai remarqué que le mode d'hydratation scalaire ne gère pas les "records listeners", de ce fait, je ne pense pas pouvoir arriver au résultat souhaité via cette méthode...


Comment auriez-vous fait pour remplacer la fonction IF() MySQL avec Doctrine ?