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

时间:2012-05-06 17:40:07

标签: php yii yii-components

我有以下型号:

User列{id,user_name,password,user_type}

Admin列{id,user_id,full_name,..... etc}

Editor列{id,user_id,full_name,... etc}

和关系是 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;


}

我可以在gridview中显示虚拟属性fullName,但是如何在属性中添加过滤器并使其在gridview中可排序?

UPADTE 1:

我根据@Jon的答案更新了模型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,


));
    }

网格视图中正确显示了管理员和编辑者的名称。但是当我通过过滤器进行搜索时,会发生以下异常,

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。

1 个答案:

答案 0 :(得分:8)

您在此处尝试执行的操作是将计算列添加到结果集中。想象一下,在用于获取结果的SQL查询中,您将加入AdminEditor表,因此Admin.full_nameEditor.full_name是将涉及的两列在计算期望值时。

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

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

现在您已经计算出公式,您需要采取以下步骤:

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

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

    道歉,如果我得到一些细节错误,因为我实际上并没有这样做。

    更新:如果您将CDbCriteria.select指定为字符串并且该字符串包含任何未用于分隔列的逗号(例如使用的逗号),则Yii不喜欢它将参数分隔为COALESCE)。值得庆幸的是,CDbCriteria还允许将列作为数组传递,从而解决了这个问题。我更新了上面的代码以匹配。

    对于任何好奇的人来说,违规代码是this