Yii - управление запросами для пользовательского CGridView с расширенным поиском - PullRequest
7 голосов
/ 03 апреля 2012

Итак, я расширил CGridView , чтобы включить функцию расширенного поиска, адаптированную к потребностям моей организации.

  • Фильтр - позволяет отображать / скрывать столбцы в таблице, а также изменять порядок столбцов, перетаскивая маленький значок перетаскивания слева от каждого элемента.
  • Сортировка - позволяет выбрать несколько столбцов, указать возрастание или убывание.
  • Поиск - Выберите столбец и вставьте параметры поиска. Операторы с учетом типа данных выбранного столбца.

Advanced Search Screenshot

Версия 1 работает, хотя и медленно. По сути, мои руки были во внутренней работе CGridView , где я получаю результаты из DataProvider и выполняю поиск и сортировку в PHP перед рендерингом содержимого таблицы.

Сейчас пишу версию 2, где я хочу сосредоточиться на умном CDbCriteria создании, позволяющем MySQL выполнять тяжелую работу, чтобы он работал быстрее. Реализация тривиальна при работе с одной таблицей базы данных. Трудность возникает, когда я имею дело с 2 или более таблицами ... Например, если пользователь намеревается выполнить поиск по полю, которое является отношением STAT , мне нужно, чтобы это отношение присутствовало в моем запросе. так что я могу включить сравнения.

Вот вопрос. Как мне убедиться, что Yii включает все with отношения в мой запрос, чтобы я включал сравнения? Я включил все свои отношения with мои критерии в функцию search модели, и я попробовал CDbCriteria's together установлено в true ...

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)
));}

Затем я выберу критерии из DataProvider и , добавлю несколько условий , например, для поиска дат> 1234567890. Но я все еще получаю ошибки, подобные этой ...

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)

Где relation0 и relation1 - это отношения BELONGS_TO, но любые отношения STAT, обозначенные здесь как relation3, отсутствуют. Кроме того, почему запрос SELECT COUNT(DISTINCT 't'.'id')?

Редактировать @DCoder Вот конкретное отношение, с которым я сейчас работаю. Основной таблицей является Call, который имеет отношение HAS_MANY к CallSegments, которое хранит время. Таким образом, startTime в Call является минимальным временем начала всех связанных CallSegment. И startTime является гипотетическим relation3 в моей ошибке анонимного запроса.

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

Редактировать Другие люди отправили меня в свойство together CDbCriteria , но, как вы можете видеть выше, я сейчас пытаюсь безрезультатно.

Редактировать Похоже, что проблема имеет , возможно, сообщалось: Yii и github tickets.

Ответы [ 2 ]

2 голосов
/ 09 апреля 2012

Это не очень хорошая идея, чтобы выхватить SQL из критериев и использовать его самостоятельно.

Если вы используете свойство «with», вы можете легко использовать сравнения, такие как:

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

Также Yii плохо работает с группировкой.

Мой подход к отношениям STAT заключается в использовании подзапроса в селекторах Yii с последующим:

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

Приведенный выше метод создает ошибку в разбивке по сетке, поскольку подсчет выполняется надругой запрос.Обходным решением будет удалить свойство «with» и самостоятельно написать соединения в свойстве «join», например:

$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 голосов
/ 12 апреля 2012

Если ошибка немного трудновата, не могли бы вы использовать отношение stat как простой HAS_ONE с:

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

, чтобы вывести значение счетчика вместе со всем остальным?

Не уверен, насколько хорошо это будет работать для вашего случая, но это было полезно для меня время от времени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...