2009-06-26 2 views
31

Ich verwende die PHP Doctrine ORM, um meine Abfragen zu erstellen. Allerdings kann ich nicht ganz auf Figur scheint, wie die folgende WHERE-Klausel DQL (Doctrine Query Language) schreiben:Komplexe WHERE-Klauseln mit der PHP-Lehre ORM

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

Wie kann ich angeben, wo die Klammern gehen?

Was ich zur Zeit in meinem PHP-Code haben, ist dies:

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

Aber das erzeugt so etwas wie

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

, die aufgrund der Reihenfolge der Operationen, nicht die gewünschten Ergebnisse nicht zurück.

Gibt es auch einen Unterschied zwischen den Methoden "where", "andWhere" und "addWhere"?

UPDATE Ok, scheint es, wie Sie nicht komplexe Abfragen mit DQL tun können, also habe ich versucht, die SQL manuell zu schreiben und die UndWo() -Methode hinzufügen verwenden. Aber ich bin mit WHERE..IN und Lehre scheint meine umschließenden Klammern werden Strippen:

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

Eine andere Lösung finden Sie hier http://stackoverflow.com/a/7720723/251735 – Jekis

Antwort

60

Aus meiner Erfahrung ist jede komplexe where Funktion in Klammern gruppiert (ich verwende Doctrine 1.2.1).

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

erzeugt die folgende SQL:

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

Genau das, was ich gesucht habe! –

+0

arbeitete für mich danke ..! –

0

Was den Unterschied zwischen dem, undwobei und addwhere, ich glaube nicht, dass es einen signifikanten Unterschied seit dem letzten Mal lese ich die Quelle. Ich möchte Sie ermutigen, die Quelle der Doktrin zu lesen. Es ist wirklich einfach und hilft, die Lücken in der Dokumentation zu füllen (es gibt viele). Was komplexere Aussagen betrifft, habe ich mich selbst gefragt, aber ich hatte noch keine Notwendigkeit dafür.

1

Wie es scheint, wie Sie nicht komplexe Abfragen mit DQL tun können, schrieb ich die folgende SQL zum UndWo() Methode übergeben:

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

Note „TRUE AND“, einen Hack, so dass Der Parser würde die äußeren Klammern nicht ignorieren.

+0

Ich denke anushr Lösung viel besser ist. Kein Hacken und Verwenden von vorbereiteten Aussagen. –

1

UndWo können wie folgt zusammengefasst werden:
zuvor hinzugefügt Bedingung (en) Aware WHERE Statement

Sie sicher UndWo inplace verwenden können von wo. (es führt einen sehr kleinen Overhead ein, der unten in dem zweiten Listenpunkt angegeben ist.)

Die Implementierung von andWhere ist: (Dok. 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); 
} 

die als gelesen werden kann,

  1. Prozessparameter
  2. append UND Anweisung wo Teil der Abfrage, , wenn ein anderes, wo Anweisung hinzugefügt wurde, bevor
  3. Append-Bedingung
0

Nach meiner Erfahrung, ich habe manchmal einen Unterschied zwischen gesehen:

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

und

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

Die erste Anweisung geschrieben ist auf drei Linien, die zweite, auf nur einen. Ich habe es nicht geglaubt, aber es gibt einen Unterschied!

8

Die korrekte Vorgehensweise hierfür finden Sie unter doctrine 2 - query builder conditional queries... If statements?, wie von @Jekis angegeben. Hier erfahren Sie, wie Sie den Ausdrucksersteller verwenden, um dies zu lösen, wie im Beispiel von @ 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); 
+4

Genau deshalb hasse ich Lehre. Das ist unmöglich zu lesen und zu verstehen. – Nicolas