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, '')

теперь что у вас есть рассчитанная формула, вам нужно сделать следующие шаги:

  1. добавьте столбец чтения и записи в модель, чтобы получить вычисляемый столбец
  2. создать CDbCriteria который соединяет две таблицы и включает вычисляемый столбец
  3. создать CSort это описывает, как вычисляемый столбец должен влиять на порядок записи
  4. создать CActiveDataProvider что использует эти критерии и параметры сортировки
  5. подача поставщика данных на ваш 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 также позволяет передавать столбцы в виде массива, который обходит эту проблему. Я обновил код выше, чтобы соответствовать.

для всех, кто любопытен, оскорбительный код этой.