2012-04-02 33 views
7

Por lo tanto, extendí CGridView para incluir una función de búsqueda avanzada adaptada a las necesidades de mi organización.Yii - Manipulación de consultas para CGridView personalizado con búsqueda avanzada

  • Filtro - le permite mostrar columnas/ocultar en la tabla, y también se puede cambiar el orden de las columnas arrastrando el icono de arrastre poco a la izquierda de cada elemento.
  • Ordenar - Permite la selección de varias columnas, especifique Ascendente o Descendente.
  • Buscar - Seleccione su columna e inserte los parámetros de búsqueda. Operadores adaptados al tipo de datos de la columna seleccionada.

Advanced Search Screenshot

Versión 1 obras, aunque lentamente. Básicamente, tuve mis manos en el funcionamiento interno de CGridView, donde recojo los resultados del DataProvider y hago la búsqueda y clasificación en PHP antes de representar los contenidos de la tabla.

Ahora escribo la Versión 2, donde pretendo centrarme en la creación inteligente de CDbCriteria, permitiendo a MySQL hacer el trabajo pesado para que funcione más rápido. La implementación es trivial cuando se trata de una tabla de base de datos única. La dificultad surge cuando estoy tratando con 2 o más tablas ... Por ejemplo, si el usuario tiene la intención de buscar en un campo que es una relación STAT, necesito que esa relación esté presente en mi consulta para que pueda incluir comparaciones .

Aquí está la pregunta. ¿Cómo puedo asegurar que Yii incluye todas las relaciones with en mi consulta para que incluya comparaciones? He incluido todas mis relaciones with mis criterios en función del modelo de search y he intentado conjunto together de CDbCriteria a cierto ...

public function search() { 
    $criteria=new CDbCriteria; 
    $criteria->compare('id', $this->id); 
    $criteria->compare(... 
    ... 
    $criteria->with = array('relation0','relation1','relation3'); 
    $criteria->together = true; 

    return new CActiveDataProvider(
     get_class($this), array(
      'criteria'=>$criteria, 
      'pagination' => array('pageSize' => 50) 
));} 

Entonces voy a arrebatar los criterios de la DataProvider y add a few conditions, por ejemplo, en busca de fechas> 1234567890. pero aún así obtener errores como este ...

CDbCommand failed to execute the SQL statement: 
SQLSTATE[42S22]: Column not found: 1054 Unknown column 't.relation3' in 'where clause'. 
The SQL statement executed was: 
SELECT COUNT(DISTINCT `t`.`id`) FROM `table` `t` 
LEFT OUTER JOIN `relation_table` `relation0` ON (`t`.`id`=`relation0`.`id`) 
LEFT OUTER JOIN `relation_table` `relation1` ON (`t`.`id`=`relation1`.`id`) 
WHERE (`t`.`relation3` > 1234567890) 

Dónde relation0 y relation1 son BELONGS_TO las relaciones, pero cualquier STAT relaciones, aquí depicte d como relation3, faltan. Además, ¿por qué la consulta es SELECT COUNT(DISTINCT 't'.'id')?

Editar @DCoder Aquí está la relación específica con la que estoy trabajando ahora. La tabla principal es Call, que tiene una relación HAS_MANY con CallSegments, que mantiene los tiempos. Por lo tanto, el startTime de la llamada es el mínimo start_time de todos los CallSegments relacionados. Y startTime es el hipotético relation3 en mi error de consulta anonimizado.

'startTime' => array(self::STAT, 'CallSegments', 'call_id', 
      'select' => 'min(`start_time`)'), 

Editar Otras personas me han enviado a CDbCriteria's together property, pero como se puede ver arriba, actualmente estoy tratando de que en vano.

Editar Parece que el problema ha pueden haber sido informados : Yii y github entradas.

+1

¿Puede mostrar más código relacionado, específicamente las declaraciones de relaciones del modelo? Las relaciones STAT generalmente se ejecutan como consultas separadas. – DCoder

+0

Bien @DCoder, agregué la relación con la que estoy trabajando ahora. ¿Quieres mas? ¿Alguna forma de incluir la relación STAT en la consulta? Pensé que para eso estaba el CDbCriteria, pero aparentemente no. –

+0

Todavía no tengo claro cuál es tu relación anónima0, relación1 y relación3, pero creo que deberás seleccionar call_id y min (start_time) en una tabla temporal y unirte a esa tabla en lugar de confiar en STAT. Si su motor de base de datos admite columnas calculadas, esa puede ser una alternativa decente. – DCoder

Respuesta

2

No es una buena idea arrebatar el sql de un criterio y usarlo usted mismo.

Si está utilizando el "con" la propiedad entonces se podría utilizar fácilmente comparaciones como:

$criteria->compare("`relation1`.`id`", $yourVarHere); 

también Yii no se comporta bien con la agrupación.

Mi acercamiento con las relaciones STAT está utilizando una subconsulta en los selecciona de Yii, seguidos por tener:

$criteria->select = array("`t`.*", "(SELECT COUNT(*) FROM `relation3` WHERE `id` = `t`.id_relation3) AS `rel3`"); 
$criteria->having = "`rel3` > " . $yourValue; 

El método anterior crea un error en la paginación gridview porque el recuento se realiza en una consulta diferente. Una solución será dejar caer el "con" la propiedad y escribir las uniones por sí mismo en la propiedad "unir" como:

$criteria->join = "LEFT OUTER JOIN `relation_table` `relation0` ON (`t`.`id`=`relation0`.`id`) 
LEFT OUTER JOIN `relation_table` `relation1` ON (`t`.`id`=`relation1`.`id`) 
LEFT OUTER JOIN `relation_table` `relation3` ON (`t`.`id`=`relation3`.`id`)"; 
0

Si el fallo es un poco difícil de conseguir trabajo podría utilizar la relación estadística como una HAS_ONE simple con:

'select'=>'count(relation3.id)', 
'joinType'=>'left join', 
'group'=>'relation3.id', 
'on'=>'t.id = relation3.id', 
'together'=>true 

para obtener el valor de conteo junto con todo lo demás?

No estoy seguro de qué tan bien funcionaría para su caso, pero me ha ayudado de vez en cuando.

Cuestiones relacionadas