Question

J'utilise PHP Doctrine ORM pour créer mes requêtes. Cependant, je n'arrive pas à comprendre comment écrire la clause WHERE suivante en utilisant DQL (Doctrine Query Language):

WHERE name='ABC' AND (category1 = 'X' OR category2 = 'X' OR category3 = 'X') 
AND price > 10

Comment puis-je spécifier où vont les parenthèses?

Voici ce que j'ai dans mon code PHP:

->where('name = ?', 'ABC')
->andWhere('category1 = ?', 'X')
->orWhere('category2 = ?', 'X')
->orWhere('category3 = ?', 'X')
->andWhere('price > ?', 10)

Mais cela produit quelque chose comme

WHERE name='ABC' AND category1 = 'X' OR category2 = 'X' OR category3 = 'X' 
AND price > 10

qui, en raison de l'ordre des opérations, ne renvoie pas les résultats escomptés.

De plus, existe-t-il une différence entre & "où &", & "et Where &" et & "addWhere &"; méthodes?

MISE À JOUR Ok, il semble que vous ne puissiez pas faire de requêtes complexes avec DQL. J'ai donc essayé d'écrire le SQL manuellement et d'utiliser la méthode andWhere () pour l'ajouter. Cependant, j'utilise WHERE..IN et Doctrine semble éliminer mes parenthèses:

$q->andWhere("(category1 IN $subcategory_in_clause
            OR category2 IN $subcategory_in_clause 
            OR category3 IN $subcategory_in_clause)");
Était-ce utile?

La solution

De mon expérience, chaque fonction where complexe est regroupée entre parenthèses (j'utilise Doctrine 1.2.1).

$q->where('name = ?', 'ABC')
  ->andWhere('category1 = ? OR category2 = ? OR category3 = ?', array('X', 'X', 'X'))
  ->andWhere('price < ?', 10)

produit le code SQL suivant:

WHERE name = 'ABC' 
  AND (category1 = 'X' OR category2 = 'X' OR category3 = 'X')
  AND price < 10

Autres conseils

Vous trouverez la bonne façon de procéder à doctrine 2 - requêtes conditionnelles du générateur de requêtes ... Si instructions? , comme l'a noté @Jekis. Voici comment utiliser le générateur d'expressions pour résoudre ce problème, comme dans l'exemple de @ anushr.

$qb->where($qb->expr()->eq('name', ':name'))
  ->andWhere(
    $qb->expr()->orX(
      $qb->expr()->eq('category1', ':category1'),
      $qb->expr()->eq('category2', ':category2'),
      $qb->expr()->eq('category3', ':category3')
  )
  ->andWhere($qb->expr()->lt('price', ':price')
  ->setParameter('name', 'ABC')
  ->setParameter('category1', 'X')
  ->setParameter('category2', 'X')
  ->setParameter('category3', 'X')
  ->setParameter('price', 10);

Comme il semble que vous ne puissiez pas effectuer de requêtes complexes avec DQL, j'ai écrit le code SQL suivant à transmettre à la méthode andWhere ():

$q->andWhere("(category1 IN $subcategory_in_clause
OR category2 IN $subcategory_in_clause 
OR category3 IN $subcategory_in_clause) AND TRUE");

Notez le & "AND TRUE &", un hack pour que l’analyseur n’ignore pas les parenthèses externes.

andWhere peut être résumé comme suit:
État (s) précédemment ajouté (s) Aware WHERE

Vous pouvez utiliser etWhere à la place de en toute sécurité. (Il introduit une très petite surcharge, ce qui est indiqué ci-dessous dans le deuxième élément de la liste.)

La mise en œuvre de andWhere is: (Doctrine 1.2.3)

public function andWhere($where, $params = array())
{
    if (is_array($params)) {
        $this->_params['where'] = array_merge($this->_params['where'], $params);
    } else {
        $this->_params['where'][] = $params;
    }

    if ($this->_hasDqlQueryPart('where')) {
        $this->_addDqlQueryPart('where', 'AND', true);
    }

    return $this->_addDqlQueryPart('where', $where, true);
}

qui peut être lu comme,

  1. Paramètres de processus
  2. ajoutez l'instruction AND à une partie de la requête, si une autre instruction où a été ajoutée avant
  3. ajouter la condition

En ce qui concerne la différence entre où, et ailleurs, et ailleurs, je ne crois pas qu'il y ait une différence significative par rapport à la dernière fois que j'ai lu la source. Je vous encourage cependant à lire la source Doctrine. C’est très simple et permet de combler les lacunes de la documentation (il y en a beaucoup). En ce qui concerne les déclarations complexes où, je me suis posé la question moi-même, mais je n’en ai pas encore eu besoin.

D'après mon expérience, j'ai parfois constaté une différence entre:

$q->andWhere("(category1 IN $subcategory_in_clause
            OR category2 IN $subcategory_in_clause 
            OR category3 IN $subcategory_in_clause)");

et

$q->andWhere("(category1 IN $subcategory_in_clause OR category2 IN $subcategory_in_clause OR category3 IN $subcategory_in_clause)");

La première déclaration est écrite sur 3 lignes, la seconde sur une seule. Je n'y croyais pas mais IL Y A UNE DIFFÉRENCE!

$q->andWhere("category1 IN ( $subcategory_in_clause )
              OR category2 IN ( $subcategory_in_clause )
              OR category3 IN ( $subcategory_in_clause )");

auriez-vous la gentillesse d'essayer cette variante, ne sachant pas si cela fonctionne, mais qui vaut le coup

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top