Filter By Custom Model Attributes

I have a custom attribute/variable in my model. I set the value for it in afterFind().


class Asd extends CActiveRecord 

{

    public $showInGridView = false;


    ...


    public function afterFind()

    {

        if(in_array($this->id, array(4, 8, 15, 16, 23, 42)))

            $this->showInGridView = true;

    }

}

How do I make a CActiveDataProvider that only gives me the results that have showInGridView attribute set to true?

Can this be done without first looping over all results and eliminating the ones we don’t want? If not, then how do I do I go about kicking the unwanted objects out?




$asds = Asd::model()->findAll();

foreach($asds as $asd)

    if(!$asd->showInGridView) unset(<img src='http://www.yiiframework.com/forum/public/style_emoticons/default/huh.gif' class='bbc_emoticon' alt='???' />); // how do I remove it? or what... I don't even... how does this work again <img src='http://www.yiiframework.com/forum/public/style_emoticons/default/smile.gif' class='bbc_emoticon' alt=':)' />?



why don’t you add your filter thing into criteria->condition for your dataprovidor, then you don’t have to hack afterfind function.

How do I add it to the condition? $criteria->addCondition(‘showInGridView = 1’); ? It would look for this variable in the database, which is not the case. Examples are welcome.

try, this:


$criteria = new CDbCriteria;

$criteria->condition = 'id in (4, 8, 15, 16, 23, 42)';

No, well, that’s not actually the condition. I evaluate the value of the custom variable with more complex functions actually. I even look into the Log which is another table on the database etc… I can’t just make sql of it. My bad for making a bad example, but let’s just say the custom variable can’t be determined before fetching the stuff, hence it’s value is set in afterFind. But my question is if I can filter by it in a GridView without manually looping through all the results, filtering out the ones I don’t want and passing the reminder off to a dataprovider. Seems like the wrong way of doing things.

Right now I do it like this and it doesn’t feel efficient:




$data = array();

$asds = Asd::model()->findAllByAttributes(...);


foreach($asds as $asd) {

	if($asd->showInGridView) array_push($data, $asd);

}


$dataProvider = new CArrayDataProvider($data, array(

	'pagination'=>false,

));



So the $dataProvider gets passed to the GridView. Hell, I don’t even want an ArrayDataprovider but I don’t know how to get an active one at this point.

Whether efficient or not, you will have to loop over all the records, since you only compute your custom field after it has been fetched from DB. IMHO you have two main options:

[list=1]

[*] use CArrayDataProvider the way you were doing so far,

[*] extend CActiveDataProvider::fetchData() method to filter by your custom field taking care to set the pagination’s item count accordingly.

[/list]

Have a look at the code.

imho, not a good idea to hack ‘view’, i agree @clapas’s approach;

we know yii has built-in visible property for column, similiar discussion in this thread, you could use similiar approach, however, you will break pagination and all good stuff in dataprovider for row