Silver
Silver

Reputation: 693

Yii - CGridView 1-to-N Display issues

I've started Yii a month ago and am finding it very intuitive, yet somehow confusing regarding widgets.

In the app i'm developing, although I sometimes use Active Record, I cannot use it's relations as I am using MyIsam (and this cannot be changed) and it has no support for foreign keys.

My issue is I have a CGridView and want to add custom data to it, but am having issues.

It is a 1-to-many relationship with the FK in the right model, but as I said, I cannot use AR's magic.

I have this, an Applications Model and a Profile model. The Profile model has an application FK.

I got a function so when I'm rendering the CGrid I can fetch the name of each Application instead of its *id_app*.

public function appName($id){
    $app= Yii::app()->db->createCommand()
        ->select('name')
        ->from('tbl_aplications a')
        ->where('a.id=:id_app', array(':id_app'=>$id))
        ->queryRow();

    return $app;
}

In the auto-generated templates, in the Profile Admin.php view, I got:

$this->widget('zii.widgets.grid.CGridView', array(
    'id'=>'profile-application-grid',
    'dataProvider'=>$model->search(), //maybe the issue is with this criteria? It is currently 'as-is' after the template generation
    'filter'=>$model,
    'columns'=>array(
        'id',
        'name',
                array(
                    'name'=>'id_app',
                    'header'=>'Aplication',

And here is my issue, I've tried (and all sorts of variations):

'value' => 'ProfileApplication::model()->appName($data->id_app)',
'value' => 'ProfileApplication::model()->appName(id_app)',
'value' => 'ProfileApplication::model()->appName("id_app")',

and all I get is null as a result because it is passing the actual string instead of each row's value. If I pass a direct ID to the function's query, it returns correct value, like ->where('a.id=:id_app', array(':id_app'=>3))

Is it the search criteria that needs to be altered? I've found similar questions but all of them use AR such as Profile->application or something along those lines and I as I said, I cannot use it due to MyIsam restrictions.

Any tips are appreciated to this newcomer, or links to a solution regarding a similar issue .

Upvotes: 1

Views: 1691

Answers (2)

JPR
JPR

Reputation: 869

To use the value attribute such as that you need, as PrplHaz4 said, a data provider. Then, the $data variable is what has the magic, and it must be used in a string because it is eval()'ed behind the scenes. Here is an example of what you are trying to do:

<?php $this->widget('zii.widgets.grid.CGridView', array(
    'id'=>'item-grid',
    'dataProvider'=>$model->search(),
    'columns'=>array(
        array(
            'name' => 'id',
            'header' => 'Item ID',

        ),
        array(
            'name' => 'category_search',
            'header' => 'Category',
            'value' => '$data->category->name',
        ),
    ),
)); ?>

That grabs the name attribute of the related item category model. In the relations() function of the item model:

return array(
    'category'=>array(self::BELONGS_TO, 'ItemCategory', 'category_id'),
);

And in the relations() function of the item category model:

return array(
    'items'=>array(self::HAS_MANY, 'Item', 'category_id'),
);

Upvotes: 2

PrplHaz4
PrplHaz4

Reputation: 412

You should still be able to use ActiveRecord relations with MyISAM, I beleive the only difference is that with MyISAM, if you use a model generator (gii or cmd line), it will not automatically create the relations. Instead, you will have to specify the relation yourself in the Profile model. This is effectively creating a "soft" fk for use with AR.

public function relations()
{
    return array(
        'applications'=>array(self::HAS_MANY, 'Applications', 'id_app'),
    );
}

That will not entirely solve your problem though, because you will need to use a dataprovider that brings the application models along with the profile models. Something like this:

$this->widget('zii.widgets.grid.CGridView', array(
  'id'=>'profile-application-grid',
  'dataProvider'=>Profile::model()->with('Applications'),
  'filter'=>$model,
  'columns'=>array(
    'id',
    'name',
    array(
      'name'=>'applications.name',
      'header'=>'Application',
    ),

Upvotes: 1

Related Questions