Yii добавьте фильтр в виртуальный атрибут в CGridView и сделайте его сортируемым

У меня есть следующие модели:

User с столбцами {id, user_name, password, user_type}

Admin с столбцами {id, user_id, full_name, ….. и т. Д.}

Editor с колонками {id, user_id, full_name, … и т. Д.}

и отношения – это User : 'admin' => array(self::HAS_ONE, 'Admin', 'user_id'),'editor' => array(self::HAS_ONE, 'Editor', 'user_id'),

Admin : 'user' => array(self::BELONGS_TO, 'User', 'user_id'),

Editor : 'user' => array(self::BELONGS_TO, 'User', 'user_id'),

Теперь я установил виртуальный атрибут fullName в User Model, как fullName ниже

 public function getFullName() { if($this->user_type=='admin') return $this->admin->full_name; else if($this->user_type=='editor') return $this->editor->full_name; } 

Я могу показать виртуальный атрибут fullName в gridview, но как добавить фильтр в атрибут и сделать его отсортированным в gridview?

UPADTE 1:

Я обновил функцию поиска () в соответствии с ответом @Jon, как показано ниже

  public function search() { $criteria=new CDbCriteria; $criteria->select=array('*','COALESCE( editor.full_name,admin.first_name, \'\') AS calculatedName'); $criteria->with=array('editor','admin'); $criteria->compare('calculatedName',$this->calculatedName,true); $criteria->compare('email',$this->email,true); $criteria->compare('user_type',$this->user_type); return new CActiveDataProvider($this, array( 'criteria'=>$criteria, )); } 

Имена администраторов и редакторов отображаются корректно в gridview. Но когда я выполняю поиск по фильтру, возникает следующее исключение,

 CDbCommand failed to execute the SQL statement: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'calculatedName' in 'where clause'. The SQL statement executed was: SELECT COUNT(DISTINCT `t`.`id`) FROM `user` `t` LEFT OUTER JOIN `editor` `editor` ON (`editor`.`user_id`=`t`.`id`) LEFT OUTER JOIN `admin` `admin` ON (`admin`.`user_id`=`t`.`id`) WHERE (calculatedName LIKE :ycp0) (C:\xampplite\htdocs\yii\framework\db\CDbCommand.php:528)</p><pre>#0 C:\xampplite\htdocs\yii\framework\db\CDbCommand.php(425): 

Как я могу избавиться от этого?

ОБНОВЛЕНИЕ 2: Моя ошибка. Он отлично работает, когда я менял строку

 $criteria->compare('calculatedName',$this->calculatedName,true); 

в

 $criteria->compare('COALESCE( editor.full_name,admin.first_name, \'\')',$this->calculatedName,true); 

и btw thanx @Jon.

Related of "Yii добавьте фильтр в виртуальный атрибут в CGridView и сделайте его сортируемым"

То, что вы пытаетесь сделать здесь, эффективно добавляет вычисляемый столбец в результирующий набор. Представьте, что в SQL-запросе, используемом для получения результатов, вы будете присоединяться к таблицам Admin и Editor , поэтому Admin.full_name и Editor.full_name – это два столбца, которые будут задействованы в вычислении желаемого значения.

Поскольку хотя бы одно имя Admin.full_name и Editor.full_name всегда будет NULL , формула для вычисления конечного значения будет

 COALESCE(Admin.full_name, Editor.full_name, '') 

Теперь, когда у вас есть вычисленная формула, вам необходимо выполнить следующие действия:

  1. Добавьте столбец чтения-записи в модель для получения расчетного столбца
  2. Создайте CDbCriteria который объединяет две таблицы и включает вычисляемый столбец
  3. Создайте CSort который описывает, как расчетный столбец должен влиять на порядок записи
  4. Создайте CActiveDataProvider который использует эти критерии и параметры сортировки
  5. CGridView поставщика данных в CGridView

Итак, сначала добавьте публичное свойство модели:

 public $calculatedName; 

А потом:

 $criteria = new CDbCriteria(array( 'select' => array( '*', 'COALESCE(Admin.full_name, Editor.full_name, \'\') AS calculatedName', ), 'with' => array('Admin', 'Editor'), // other options here )); $sort = new CSort; $sort->attributes = array( 'calculatedName' => array( 'asc' => 'COALESCE(Admin.full_name, Editor.full_name, \'\')', 'desc' => 'COALESCE(Admin.full_name, Editor.full_name, \'\') DESC', ), // other sort order definitions here ); $dataProvider = new CActiveDataProvider('User', array( 'criteria' => $criteria, 'sort' => $sort, )); 

И, наконец, используйте $dataProvider для заполнения вашей сетки; используйте calculatedName как имя столбца.

Извиняюсь, если у меня есть некоторые детали не так, как я на самом деле не запускал это.

Обновление: Оказывается, Yii не нравится, если вы укажете CDbCriteria.select как строку, и эта строка содержит любые запятые, которые не используются для разделения столбцов (например, запятые, используемые для разделения аргументов COALESCE ). К счастью, CDbCriteria также позволяет передавать в столбцах массив, который оборачивается этой проблемой. Я обновил код выше, чтобы соответствовать.

Для любого, кто любопытен, это нарушительный код.