web-dev-qa-db-fra.com

Clauses WHERE complexes utilisant le PHP Doctrine ORM

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?

Ce que j'ai actuellement dans mon code PHP est le suivant:

->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.

En outre, y a-t-il une différence entre les méthodes "where", "andWhere" et "addWhere"?

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

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

D'après 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
68
anushr

La bonne façon de faire cela peut être trouvée à doctrine 2 - requêtes conditionnelles du constructeur de requêtes ... déclarations Si? 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);
15
David Baucum

andWhere peut se résumer comme suit:
Condition précédemment ajoutée (s) Conscient de la déclaration WHERE

Vous pouvez utiliser en toute sécurité andWhere inplace of where . (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. ajoute l'instruction ET à une partie de la requête, si une autre instruction où a été ajoutée auparavant
  3. ajouter la condition
1
Lashae

Comme il semble que vous ne puissiez pas faire 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 "ET VRAI", un hack pour que l’analyseur n’ignore pas les parenthèses externes.

1
Wickethewok

En ce qui concerne la différence entre où, et ailleurs, et addwhere, 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.

0
Bob Gettys

Dans mon expérience, j'ai parfois vu 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 là IS une différence!

0
baboush