2009-06-26 14 views
31

Estoy usando PHP Doctrine ORM para crear mis consultas. Sin embargo, no puedo parecer bastante para averiguar cómo escribir la siguiente cláusula WHERE usando DQL (Lenguaje de Consulta Doctrina):Cláusulas WHERE complejas que usan la Doctrina PHP ORM

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

¿Cómo puedo especificar dónde van los paréntesis?

Lo que tengo actualmente en mi código PHP es la siguiente:

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

Pero esto produce algo así como

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

que, por orden de las operaciones, no devuelve los resultados esperados.

Además, ¿hay alguna diferencia entre los métodos "where", "andWhere" y "addWhere"?

ACTUALIZACIÓN Ok, parece que no se puede hacer consultas complejas utilizando DQL, por lo que he estado tratando de escribir el código SQL de forma manual y utilizar el método andWhere() para añadirla. Sin embargo, estoy usando WHERE..IN y Doctrina parece estar excluyendo mis paréntesis que encierran:

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

Otra solución se puede encontrar aquí http://stackoverflow.com/a/7720723/251735 – Jekis

Respuesta

60

Desde mi experiencia, cada función compleja where está agrupada entre paréntesis (estoy usando Doctrine 1.2.1).

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

produce el siguiente SQL:

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

¡Exactamente lo que estaba buscando! –

+0

funcionó para mí gracias ..! –

0

En cuanto a la diferencia entre el lugar donde, andwhere y addwhere, yo no creo que hay una diferencia significativa desde la última vez que leí la fuente. Sin embargo, te animo a que leas la fuente de Doctrine. Es realmente simple y ayuda a llenar los huecos en la documentación (hay muchos). En cuanto a las declaraciones complejas, me he preguntado esto pero todavía no lo he necesitado.

1

Como parece que no se puede hacer consultas complejas utilizando DQL, escribí el siguiente código SQL para pasar a la andWhere() Método:

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

Nota de la "Y VERDADERO", un corte de manera que el analizador no ignoraría los paréntesis externos.

+0

Creo que la solución de anushr es mucho mejor. Sin piratería y uso de declaraciones preparadas. –

1

andWhere se puede resumir como:
Condición (s) Anteriormente Añadido Consciente DONDE Declaración

Usted puede utilizar con seguridad andWhere inplace de donde. (introduce una sobrecarga muy pequeña, que se indica a continuación en el elemento de la segunda lista.)

La implementación 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); 
} 

que puede ser leído como,

  1. parámetros del proceso
  2. anexar Y declaración a donde parte de la consulta, si otro donde se añadió declaración ante
  3. append condición
0

En mi experiencia, a veces he visto una diferencia entre:

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

y

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

La primera sentencia está escrita en 3 líneas, la segunda y primera. ¡No lo creí, pero HAY UNA DIFERENCIA!

8

La forma correcta de hacer esto se puede encontrar en doctrine 2 - query builder conditional queries... If statements? según lo observado por @Jekis. Aquí es cómo usar el constructor de expresiones para resolver esto como en el ejemplo 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); 
+4

Esto es exactamente por qué odio Doctrine. Esto es imposible de leer y entender. – Nicolas

Cuestiones relacionadas