Précédent   Forum des professionnels en informatique > PHP > Bibliothèques et frameworks > symfony
symfony Forum d'entraide sur le framework PHP symfony. Avant de poster : cours symfony et FAQ symfony
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 31/05/2011, 09h32   #1
Nouveau Membre du Club
 
Inscription : mars 2007
Messages : 311
Détails du profil
Informations forums :
Inscription : mars 2007
Messages : 311
Points : 33
Points : 33
Par défaut requête doctrine: probleme d'exécution andWhereIn et orWhereIn

Bonjour,
j'ai un souci avec l'exécution d'une requête utilisant les "andWhereIn" et "orWhereIn", j'ai pas vraiment le résultat que je veux obtenir.

ce que je voudrais faire c'est : A and (B or C or D) sachant que les valeurs de B, C et D se trouvent en array, voici mon code:

Code :
1
2
3
4
5
6
7
8
9
 
	$this->articles = Doctrine::getTable('article')->createQuery('a')
       ->where('a.fournisseur = ?', 'ldt') // représente A
        ->innerJoin('a.Coordonnes p' )
	  ->innerJoin('a.Codes m' )
      ->innerJoin('a.Symboles g' )
      ->andWhereIn('p.nom', array(...,..,..,...)) // représente B
    ->orWhereIn('m.code', array(..,..,..,...)) // représente C
    ->orWhereIn('g.symbole', array(..,..,..,...)) // représente D
le résultat de ce code ne prend pas en compte la condition " ->where('a.fournisseur = ?', 'ldt')",
quelqu'un a une idée?

merci !
flora806 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/05/2011, 17h01   #2
Modérateur
 
Avatar de Michel Rotta
 
Homme Michel Rotta
Responsable d'exploitation informatique
Inscription : septembre 2005
Messages : 4 913
Détails du profil
Informations personnelles :
Nom : Homme Michel Rotta
Âge : 49
Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Responsable d'exploitation informatique
Secteur : Distribution

Informations forums :
Inscription : septembre 2005
Messages : 4 913
Points : 7 505
Points : 7 505
Tu es dans les limites de ce que sait faire le DQL.

Il faut regrouper tous dans un seul andWhere.

Code :
1
2
 
->andWhere('p.nom IN :nom: AND (m.code IN :code: OR g.symbole IN :sym:', array( ':non:' => array(...), ':code:' => array(...), ':sym:' => array(...) )
Je sais que cela marche avec des string, je suppose avec des IN et des array, mais à essayer.
__________________
Si tu donnes un poisson à un homme, il mangera un jour. Si tu lui apprends à pêcher, il mangera toujours (Lao Tseu).
  • Pensez à valoriser les réponses pertinantes, cliquez sur le bouton vert +1 pour indiquer votre accord avec la solution proposée.
  • Pensez à utiliser la balise [code] pour afficher du code, elle est cachée sous le bouton [#] dans l'éditeur.
  • Une discussion est terminée ? Alors le bouton est votre ami !
Michel Rotta est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 01/06/2011, 10h02   #3
Nouveau Membre du Club
 
Inscription : mars 2007
Messages : 311
Détails du profil
Informations forums :
Inscription : mars 2007
Messages : 311
Points : 33
Points : 33
Merci Michel,
j'ai essayé ton code, mais ça ne fonctionne pas il y a des erreurs pour les ":nom:"...
j'ai essayé un autre code, mais qui marche à moitié ,

Citation:
$noms = array(....);
$cod = array(..........);
$sym = array(.........);

$this->articles = Doctrine::getTable('article')->createQuery('a')
->innerJoin('a.Coordonnes p' )
->innerJoin('a.Codes m' )
->innerJoin('a.Symboles g' )
->andWhere('a.fournisseur = ?', 'ldt')
->andWhereIn("(p.nom IN $noms OR
m.code IN $cod OR g.symbole IN $sym )AND TRUE")
en fait dans la ligne:
Code :
1
2
3
 
->andWhereIn("(p.nom IN $noms OR 
     m.code IN $cod OR g.symbole IN $sym )AND TRUE")
c'est plus un AND qu'il me fait à la place des OR
flora806 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/06/2011, 11h29   #4
Modérateur
 
Avatar de Michel Rotta
 
Homme Michel Rotta
Responsable d'exploitation informatique
Inscription : septembre 2005
Messages : 4 913
Détails du profil
Informations personnelles :
Nom : Homme Michel Rotta
Âge : 49
Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Responsable d'exploitation informatique
Secteur : Distribution

Informations forums :
Inscription : septembre 2005
Messages : 4 913
Points : 7 505
Points : 7 505
A bien y réfléchir, mon code ne peut pas fonctionner, il ne comprendrait pas les IN et ne pourrait générer correctement le SQL à partir des array...

Je ne comprend pas ton code dans le andWhereIn(), ni pourquoi tu lui rajoute un "AND TRUE" qui n'apporte pas grand chose.

Je ne vois, là, qu'une solution. L'utilisation d'un andWhere() (et pas d'un andWhereIn() ) qui sera la représentation complète de ce que tu veux, à toi de créer l'ensemble de la string qui sera ta requête, à toi aussi de vérifier que les données dans les tableaux ne peuvent embarquer de code d'injection sql.
__________________
Si tu donnes un poisson à un homme, il mangera un jour. Si tu lui apprends à pêcher, il mangera toujours (Lao Tseu).
  • Pensez à valoriser les réponses pertinantes, cliquez sur le bouton vert +1 pour indiquer votre accord avec la solution proposée.
  • Pensez à utiliser la balise [code] pour afficher du code, elle est cachée sous le bouton [#] dans l'éditeur.
  • Une discussion est terminée ? Alors le bouton est votre ami !
Michel Rotta est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/06/2011, 13h51   #5
Nouveau Membre du Club
 
Inscription : mars 2007
Messages : 311
Détails du profil
Informations forums :
Inscription : mars 2007
Messages : 311
Points : 33
Points : 33
le problème c'est que je trouve pas suffisamment de doc sur les requêtes doctrine avec l'utilisation à la fois de andWhere et orWhere, j'ai essayé plein de choses, j'arrive pas à trouver la bonne syntaxe.
dernier essai:

Code :
1
2
3
4
 
.......
->andWhere('a.fournisseur = ?', 'ldt')
->andWhere('g.symbole = ?', $sym OR 'm.code = ?' $cod)
--> Erreur: Parse error: syntax error, unexpected T_VARIABLE ...
le andWhereIn, c'était pour pouvoir utiliser IN array()..

des idées de syntaxe?
flora806 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/06/2011, 14h10   #6
Membre habitué
 
Homme Ludovic
Étudiant
Inscription : janvier 2011
Messages : 124
Détails du profil
Informations personnelles :
Nom : Homme Ludovic
Localisation : France

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : janvier 2011
Messages : 124
Points : 140
Points : 140
Juste pour information : http://www.doctrine-project.org/proj...n#where-clause
PeytaWodka est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/06/2011, 14h36   #7
Nouveau Membre du Club
 
Inscription : mars 2007
Messages : 311
Détails du profil
Informations forums :
Inscription : mars 2007
Messages : 311
Points : 33
Points : 33
merci pour l'info, mais je trouve pas vraiment la syntaxe qui correspond à mon cas : A AND (B OR C ) , sachant que les valeurs de B et C sont récupérés à partir d'array..

le résultat que j'obtiens correspond à A AND B AND C, est-ce que ça peut venir des suites de innerJoin?
flora806 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/06/2011, 17h00   #8
Modérateur
 
Avatar de Michel Rotta
 
Homme Michel Rotta
Responsable d'exploitation informatique
Inscription : septembre 2005
Messages : 4 913
Détails du profil
Informations personnelles :
Nom : Homme Michel Rotta
Âge : 49
Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Responsable d'exploitation informatique
Secteur : Distribution

Informations forums :
Inscription : septembre 2005
Messages : 4 913
Points : 7 505
Points : 7 505
Relis mon précédant poste, c'est à mon avis la seule solution.
__________________
Si tu donnes un poisson à un homme, il mangera un jour. Si tu lui apprends à pêcher, il mangera toujours (Lao Tseu).
  • Pensez à valoriser les réponses pertinantes, cliquez sur le bouton vert +1 pour indiquer votre accord avec la solution proposée.
  • Pensez à utiliser la balise [code] pour afficher du code, elle est cachée sous le bouton [#] dans l'éditeur.
  • Une discussion est terminée ? Alors le bouton est votre ami !
Michel Rotta est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/06/2011, 12h08   #9
Membre actif
 
Homme Fabrice Agnello
Développeur informatique
Inscription : octobre 2010
Messages : 76
Détails du profil
Informations personnelles :
Nom : Homme Fabrice Agnello
Âge : 39
Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Développeur informatique
Secteur : Industrie

Informations forums :
Inscription : octobre 2010
Messages : 76
Points : 161
Points : 161
Bonjour,

comme vous le signale Michel Rotta, vous ne pouvez pas réaliser ce genre de requête avec le fonctionnement par défaut du DQL.

Une solution est de définir votre propre classe de query à partir de Doctrine_Query en ajoutant une notion de "nested condition".

Une base pour la classe que vous pourrez utiliser est la suivante (nécessitera peut-être d'être retravaillée, car non testée en profondeur):
Code php :
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
 
/**
 * Sep_Query class.
 *
 * This class adds a new behaviour to the standard Doctrine_Query by allowing
 * nested conditions in the where statement
 *
 * @package    sep
 * @author     Fabrice AGNELLO
 */
class Sep_Query extends Doctrine_Query{
  /**
   * the nested query parts
   * @var Sep_Query
   */
  protected $_nested_conditionnal_part = array();
 
  /**
   * create
   * returns a new Sep_Query object
   *
   * @param Doctrine_Connection $conn  optional connection parameter
   * @param string $class              Query class to instantiate
   * @return Sep_Query
   */
  public static function create($conn = null, $class = null)
  {
    //overloading, just returns the Seq_Query object
    return parent::create($conn, 'Sep_Query');
  }
 
  /**
   *
   * @param Sep_Query $q
   * @param string $operator
   * @return Sep_Query
   */
  protected function nestedWhere(Sep_Query $q, $operator){
    $this->_nested_conditionnal_part[] = array('query' => $q, 'operator' => $operator);
    return $this;
  }
 
  /**
   * addNestedWhere
   * returns the current Sep_Query object
   * @param Sep_Query the query part object
   * @return Sep_Query
   */
  public function addNestedWhere(Sep_Query $q){
    $this->nestedWhere($q, 'and');
    return $this;
  }
 
  /**
   * andNestedWhere
   * returns the current Sep_Query object
   * @param Sep_Query the query part object
   * @return Sep_Query
   */
  public function andNestedWhere(Sep_Query $q){
    $this->nestedWhere($q, 'and');
    return $this;
  }
 
  /**
   * orNestedWhere
   * returns the current Sep_Query object
   * @param Sep_Query the query part object
   * @return Sep_Query
   */
  public function orNestedWhere(Sep_Query $q){
    $this->nestedWhere($q, 'or');
    return $this;
  }
 
  /**
   * @see Doctrine_Query_Abstract::execute()
   */
  public function execute($params = array(), $hydrationMode = null)
  {
    // get the inner conditionnal parts
    foreach($this->_nested_conditionnal_part as $condition){
      $additional_condition = '';
      foreach($condition['query']->_dqlParts['where'] as $condition_element){
        if($condition_element == 'AND' || $condition_element == 'OR')
          $additional_condition .= ' '.$condition_element.' ';
        else
          $additional_condition .= '('.$condition_element.')';
      }
 
      if($condition['operator'] == 'or')
        $this->orWhere($additional_condition, $condition['query']->_params['where']);
      else
        $this->andWhere($additional_condition, $condition['query']->_params['where']);
    }
    // execute query
    return parent::execute($params, $hydrationMode);
  }
}

son utilisation est alors très simple :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
    $cnx = Doctrine_Core::getConnectionByTableName('Jobeet_Job');
    $q = Sep_Query::create($cnx);

    $q->from('JobeetJob')
      ->where('category_id = ?', 18)
      ->andWhere('id between ? and ?', array(36, 60))
      ->andNestedWhere(Sep_Query::create()->andWhere('is_activated is not null')
                                          ->orWhereIn('category_id', array(17,18,19)))
      ->andWhere('id between ? and ?', array(38, 45));

    $this->res = $q->execute();
ce qui donne en résultat :
Code php :
1
2
 
SELECT j.id AS j__id, j.category_id AS j__category_id, j.type AS j__type, j.company AS j__company, j.logo AS j__logo, j.url AS j__url, j.position AS j__position, j.location AS j__location, j.description AS j__description, j.how_to_apply AS j__how_to_apply, j.token AS j__token, j.is_public AS j__is_public, j.is_activated AS j__is_activated, j.email AS j__email, j.expires_at AS j__expires_at, j.created_at AS j__created_at, j.updated_at AS j__updated_at FROM jobeet_job j WHERE (j.category_id = ? AND j.id BETWEEN ? AND ? AND j.id BETWEEN ? AND ? AND (j.is_activated is not null OR j.category_id IN (?, ?, ?)))

avec les paramètres passés dans l'ordre correct attendu :
Code php :
1
2
 
(18, 36, 60, 38, 45, 17, 18, 19)

HTH.
Agnello Fabrice est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 17h33.


 
 
 
 
Partenaires

Hébergement Web