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
модель ниже
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:xampplitehtdocsyiiframeworkdbCDbCommand.php:528)</p><pre>#0 C:xampplitehtdocsyiiframeworkdbCDbCommand.php(425):
как я могу избавиться от этого?
обновление 2: Моя ошибка. Он отлично работает, когда я изменил строку
$criteria->compare('calculatedName',$this->calculatedName,true);
to
$criteria->compare('COALESCE( editor.full_name,admin.first_name, '')',$this->calculatedName,true);
и кстати thanx @Jon.
1 ответов
то, что вы пытаетесь сделать здесь, это эффективно добавить вычисляемый столбец в результирующем наборе. Представьте, что в SQL-запросе, используемом для получения результатов, вы присоединитесь к обоим Admin
и Editor
таблицы, так Admin.full_name
и Editor.full_name
две колонны, которые будут участвовать в вычислении требуемого значения.
так как по крайней мере один Admin.full_name
и Editor.full_name
всегда NULL
, формула для вычисления конечного значения будет
COALESCE(Admin.full_name, Editor.full_name, '')
теперь что у вас есть рассчитанная формула, вам нужно сделать следующие шаги:
- добавьте столбец чтения и записи в модель, чтобы получить вычисляемый столбец
- создать
CDbCriteria
который соединяет две таблицы и включает вычисляемый столбец - создать
CSort
это описывает, как вычисляемый столбец должен влиять на порядок записи - создать
CActiveDataProvider
что использует эти критерии и параметры сортировки - подача поставщика данных на ваш
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
также позволяет передавать столбцы в виде массива, который обходит эту проблему. Я обновил код выше, чтобы соответствовать.
для всех, кто любопытен, оскорбительный код этой.