10

我有以下型号:

User列 {id,user_name,password,user_type}

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

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;


}

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

更新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);

顺便说一句,谢谢@Jon。

4

1 回答 1

8

您在这里尝试做的是有效地将计算列添加到结果集中。想象一下,在用于获取结果的 SQL 查询中,您将连接AdminEditor表,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列名。

如果我弄错了一些细节,我深表歉意,因为我实际上并没有运行它。

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

对于任何好奇的人,有问题的代码是this

于 2012-05-06T22:47:58.327 回答