querybuilder - Cláusulas WHERE complejas que utilizan el PHP Doctrine ORM
symfony 3.4 doctrine query (6)
Como parece que no puedes hacer consultas complejas usando DQL, escribí el siguiente SQL para pasar al método andWhere ():
$q->andWhere("(category1 IN $subcategory_in_clause
OR category2 IN $subcategory_in_clause
OR category3 IN $subcategory_in_clause) AND TRUE");
Tenga en cuenta el "Y VERDADERO", un truco para que el analizador no ignore los paréntesis externos.
Estoy usando PHP Doctrine ORM para construir mis consultas. Sin embargo, no puedo entender cómo escribir la siguiente cláusula WHERE usando DQL (Doctrine Query Language):
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 este:
->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, debido al orden de las operaciones, no devuelve los resultados previstos.
Además, ¿hay alguna diferencia entre los métodos "where", "andWhere" y "addWhere"?
ACTUALIZACIÓN Ok, parece que no puedes hacer consultas complejas usando DQL, así que he intentado escribir el SQL manualmente y usar el método andWhere () para agregarlo. Sin embargo, estoy usando WHERE..IN y Doctrine parece estar eliminando mis paréntesis adjuntos:
$q->andWhere("(category1 IN $subcategory_in_clause
OR category2 IN $subcategory_in_clause
OR category3 IN $subcategory_in_clause)");
Desde mi experiencia, cada complejo where
función 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
En cuanto a la diferencia entre where, wherewhere y addwhere, no creo que haya una diferencia significativa con respecto a 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.
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 declaración está escrita en 3 líneas, la segunda, en una sola. ¡No lo creí, pero HAY UNA DIFERENCIA!
La forma correcta de hacer esto se puede encontrar en la doctrina 2 - consultas condicionales del generador de consultas ... ¿Si las declaraciones? como lo señala @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);
y donde se puede resumir como:
Condición (s) Anteriormente Agregada (s) Consciente Declaración WHERE
Puede usar de forma segura y donde en el lugar de donde . (introduce una sobrecarga muy pequeña, que se indica a continuación en el segundo elemento de la 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 se puede leer como,
- Parámetros de proceso
- añadir instrucción AND a la parte de la consulta, si se agregó otra instrucción where
- añadir condición