Using virtual attributes in a model -> a discrepancy IMHO #1899

Closed
Ziggizag opened this Issue Dec 29, 2012 · 2 comments

4 participants

@Ziggizag

I have a problem to call it a bug... this is more like a design flaw.
Let me explain:

Presume we have a model with two attributes:

'forename' and 'surname'

Then, we want to show the active record data using a calculated column (a virtual attribute) called 'fullname'.

So we declare a new attribute within a model:

public $fullname;

function getFullname()
{
return $this->surname . ', ' . $this->forename;
}

We would expect this is enough to use this new virtual attribute for search criteria but we fail. We see all search is accomplished via pretty direct databes queries, so we need to wriite more code:

public function search()
{
$criteria=new CDbCriteria;
$criteria->select = array('*', 'CONCAT(surname, ", ", forename) AS fullname');
$criteria->compare('CONCAT(surname, ", ", forename)', $this->fullname, true);

return new CActiveDataProvider($this, array(
    'criteria'=>$criteria,
    'pagination'=>array('pageSize'=>10),
     'sort' => array(
                  'attributes'=>array('CONCAT(surname, ", ", forename) AS fullname',),
                  'defaultOrder' => 'fulname ASC',
             ),
));

}

Well - we are near happy solution but... we can immediately notice that "Fullname" column displayed in CGridView is not sortable. The question is... WHY ???

And the nasty answer is, because CSort class resoves attributes using:

CActiveRecord::model($this->modelClass)->hasAttribute($attribute)

And 'hasAttribute' method of CActiveRecord is entirely based on CActiveRecordMetaData, so it is completely unaware of our virtual attributes behind a computed column!

This is a desgin flaw in my humble opinion. I am afraid it is the origin of multiple problems with usage of computed columns in the scope of active records what cannot be easily resolved because virtual attributes are not being recognized by 'hasAttribute' method.

Please - think about and comment if feasible! And even better - correct it if necessary!

@velobuff
@Ziggizag

A fellow Yii forum member seenivasan instructed me of this working solution:

$sort->attributes = array('*', "fullname"=>array(
"asc"=>"CONCAT(surname, ", ", forename) ASC",
"desc"=>"CONCAT(surname, ", ", forename) DESC",
));

Anyway - IMHO - all these is just a workaround. It would be much more simple if virtual attributes were recognized by 'hasAttribute' method.

@cebe cebe was assigned Jan 8, 2013
@samdark samdark closed this Nov 17, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment