Php Yii向CGridView中的虚拟属性添加过滤器并使其可排序

Php Yii向CGridView中的虚拟属性添加过滤器并使其可排序,php,yii,yii-components,Php,Yii,Yii Components,我有以下型号: User列{id、用户名、密码、用户类型} Admin带有列{id、user\u id、full\u name,…等} 编辑器包含列{id、user\u id、full\u name等} 关系是 User:'admin'=>数组(self::HAS_ONE,'admin','User_id'),'editor'=>数组(self::HAS_ONE,'editor','User_id'), Admin:“用户”=>数组(self::属于“用户”、“用户id”), 编辑器:“用户”=

我有以下型号:

User
列{id、用户名、密码、用户类型}

Admin
带有列{id、user\u id、full\u name,…等}

编辑器
包含列{id、user\u id、full\u name等}

关系是
User
'admin'=>数组(self::HAS_ONE,'admin','User_id'),'editor'=>数组(self::HAS_ONE,'editor','User_id'),

Admin
“用户”=>数组(self::属于“用户”、“用户id”),

编辑器
“用户”=>数组(self::属于“用户”、“用户id”),

现在我在
User
模型中设置了一个虚拟属性
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;


}
我可以在gridview中显示虚拟属性
fullName
,但如何向属性添加筛选器并使其在gridview中可排序

UPADTE 1:

我根据@Jon的答案更新了models search()函数,如下所示

    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):


顺便说一句,thanx@Jon.

这里要做的就是有效地向结果集中添加一个计算列。假设在用于获取结果的SQL查询中,您将加入
Admin
Editor
表,因此
Admin.full\u name
Editor.full\u name
是计算所需值所涉及的两列

由于至少有一个
Admin.full_name
Editor.full_name
始终为
NULL
,因此计算最终值的公式为

public $calculatedName;
现在您已经有了计算公式,需要执行以下步骤:

  • 向模型中添加读写列以接收计算列
  • 创建一个连接两个表并包含计算列的
    CDbCriteria
  • 创建一个描述计算列如何影响记录顺序的
    CSort
  • 创建一个使用这些条件和排序选项的
    CActiveDataProvider
  • 将数据提供程序提供给您的
    CGridView
  • 因此,首先将公共属性添加到模型中:

    $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
    作为列名

    如果我弄错了一些细节,我会道歉,因为我实际上并没有运行这个

    更新:如果指定
    CDbCriteria,Yii不喜欢它。选择
    作为字符串,该字符串包含任何不用于分隔列的逗号(例如用于分隔
    合并的参数的逗号)。谢天谢地,
    CDbCriteria
    还允许以数组形式传入列,这就解决了这个问题。我更新了上面的代码以匹配


    对于任何好奇的人来说,令人不快的代码是。

    我不知道我做错了什么,但我一直收到这个错误CDBEException:活动记录“用户”试图选择一个无效的列“合并(管理员全名)”。注意,该列必须存在于表中,或者是一个别名为的表达式。@dInGd0nG:你没有做错什么,我发布的答案正好与Yii的一个小怪癖相冲突。请参阅update.okey。更新工作正常。但我不能使用
    $criteria->compare('fullName',$this->calculatedName,true)
    当我在CGridView过滤器中进行搜索时,出现以下异常情况CDbCommand无法执行SQL语句:SQLSTATE[42S22]:未找到列:1054“where子句”中的未知列“calculatedName”。执行的SQL语句是:SELECT COUNT(DISTINCT
    t
    id
    )从(
    editor
    user\u id
    =
    t
    t
    t
    id
    id
    )上(
    admin
    用户id
    用户id
    )上的左外连接
    admin
    ),其中(计算名称如:ycp0)@dInGd0nG:如果您发布相关代码作为问题的更新,这将非常有用。无论如何,我认为要在列上进行筛选,您需要手动添加它,例如
    $criteria->condition=“COALESCE(…)LIKE“%$var%””
    ,用一个适当的带引号的表达式替换
    $var
    。计算列确实很麻烦。
    COALESCE(Admin.full_name, Editor.full_name, '')
    
    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,
    ));