2010-12-07 9 views
15

Quiero generar este complejo cláusula WHERE en Zend_Db:Complejo cláusula WHERE con Zend_Db utilizando múltiples y operadores OR

SELECT * 
FROM 'products' 
WHERE 
    status = 'active' 
    AND 
    (
     attribute = 'one' 
     OR 
     attribute = 'two' 
     OR 
     [...] 
    ) 
; 

He intentado esto:

$select->from('product'); 
$select->where('status = ?', $status); 
$select->where('attribute = ?', $a1); 
$select->orWhere('attribute = ?', $a2); 

y que produje:

SELECT `product`.* 
FROM `product` 
WHERE 
    (status = 'active') 
    AND 
    (attribute = 'one') 
    OR 
    (attribute = 'two') 
; 

Descubrí un método para hacer este trabajo pero sentí que era una especie de "trampa" al usar PHP para combinar el "OR" primero las cláusulas y luego combinarlas usando Zend_Db where() cláusula. Código PHP:

$WHERE = array(); 
foreach($attributes as $a): 
    #WHERE[] = "attribute = '" . $a . "'"; 
endforeach; 
$WHERE = implode(' OR ', $WHERE); 

$select->from('product'); 
$select->where('status = ?', $status); 
$select->where($WHERE); 

Eso produjo lo que estaba buscando. Pero tengo curiosidad si hay una forma "oficial" de obtener esa declaración WHERE compleja (que en realidad no es demasiado compleja, solo agrega algunos paréntesis) con el uso de la herramienta Zend_Db, en lugar de combinarla en PHP primero.

¡Salud!

Respuesta

20

Esta sería la forma 'oficial' para conseguir que los paréntesis, como se especifica (ver Ejemplo # 20 en la documentación Zend_Db_Select):

$a1 = 'one'; 
$a2 = 'two'; 
$select->from('product'); 
$select->where('status = ?', $status); 
$select->where("attribute = $a1 OR attribute = $a2"); 

Por lo tanto, lo que está haciendo parece razonable, dado que no sé cuántos atributos tienes antes de tiempo.

+0

Sí, su solución, de la guía de referencia de ZF, es básicamente cómo se me ocurrió el último ejemplo. Tal vez esa es la forma correcta de hacerlo en ese momento. Simplemente se siente contrario a la intuición dado que Zend_Db_Select (ZDS) se supone que debe generar su SQL para usted, pero tenemos que generar una parte de él fuera de ZDS. Tal vez, esto es algo que podría usar una extensión para que podamos mantener todo el código en Zend_Db_Select. – jmbertucci

+0

El enlace [Zend_Db_Select] (http://framework.zend.com/manual/1.12/en/zend.db.select.html) no funcionó para mí aquí hay un enlace actualizado a los documentos. –

0

Utilizo esta solución y parece que funciona como quería.

$select->from('product'); 
$select->where('status = ?', $status); 
$select->where('(attribute = ?', $a1); 
$select->orWhere('attribute = ?)', $a2); 
2

Si se utiliza la respuesta elegida tendría que recordar a citar a los valores antes de construir la consulta para evitar la inyección de SQL.

Otra opción que utiliza Zend Db Seleccionar para crear la consulta y cita también a los valores serían de hacerlo en 2 etapas:

/// we just use this select to create the "or wheres" 
$select1->from('product'); 
foreach($attributes as $key => $a) { 
    if ($key == 0) { 
    /// we don't want "OR" for first one 
     $select1->where("attribute = ?", $a); 
    } else { 
     $select1->orWhere("attribute = ?", $a); 
    } 
} 

/// now we construct main query 
$select2->from('product'); 
$select2->where('status = ?', $status); 
$select2->where(implode(' ', $select1->getPart('where'))); 

De esta manera Zend Db Select hace todo el generatation SQL. Una vieja pregunta, pero espero que esta idea pueda ser útil para alguien con un problema similar.

0

Si el atributo es la misma columna de la tabla y desea comprobar igual a uno de varios valores, que se pueden utilizar en:

$select->from('product'); 
$select->where('status = ?', $status); 
$select->where('attribute IN (?)', [$a1, $a2, ...]); 

o

$select->where('attribute IN (:someName)'); 
$select->setParameter('someName', [$a1, $a2, ...]); 

De lo contrario veo ninguna alternativa a la decisión anterior con "attribute = $a1 OR attribute = $a2"