Relational attributes in CActiveDataProvider and CDbCriteria using "with"

Hello Yii forums, I’m having an issue trying to display some relational data in a CGridView. Before anyone else refers me to these, I have already read over http://www.yiiframework.com/forum/index.php?/topic/14462-how-to-display-relational-data/page__p__71751__hl__relational+attribute+dataprovider and http://www.yiiframework.com/forum/index.php?/topic/14390-search-for-many-many-value-in-cgridview/ and found the solutions there to be inconclusive or not directly related to my issue.

My criteria and data providers:


$oSdkCriteria = new CDbCriteria( array(

   'condition' => '('.$this->sGetSubmissionIdsSQL( false,'sub' ).') AND ( (sub.status>0 AND sub.status<5) OR ( ( sub.status=6 OR sub.status=5 ) AND sub.time_out>:one_week) )',

   'params'    => array(':one_week' => $iOneWeekPrev),

   'select' => array(

      'game_id', 'base', 'build', 'priority',  'exp_out', 'type', 'id', 'status'

   ),

   'alias' => 'sub', // need to use the alias in a number of places to kill ambiguity

   'with' => array( 'game'=>array( 'alias'=>'gm', 'select' => 'name, status, rel_date, id') ),

));


$oSdkSort = new CSort( 'GameSubmission' );

$oSdkSort->separators = array(',',':');

$oSdkSort->attributes = array(

   'name' => array(

      'label' => 'Game',

      'asc' => 'name ASC',

      'desc' => 'name DESC',

   ),

   'version' => array(

      'label' => 'Version',

      'asc' => 'build asc',

      'desc' => 'build desc',

   ),

   'priority' => array(

      'label' => 'Priority',

      'asc' => 'ISNULL(priority), priority desc',

      'desc' => 'ISNULL(priority), priority asc',

   ),

   'release' => array(

      'label' => 'Game Rel. Date',

      'asc' => 'ISNULL(rel_date), rel_date asc',

      'desc' => 'ISNULL(rel_date), rel_date desc',

   ),

   'status' => array(

      'label' => 'Status',

      'asc' => 'sub.status asc',

      'desc' => 'sub.status desc',

   ),

);

$oSdkSort->multiSort = false;

$oSdkSort->defaultOrder = array( 'priority' => true, );


$oSdkData = new CActiveDataProvider( 'GameSubmission', array(

   'pagination'=> array(

      'pageSize' => isset( $_GET['sdk_status'.'_pageSize'] ) ? $_GET['sdk_status'.'_pageSize'] : 15,

   ),

   'criteria'   => $oSdkCriteria,

   'sort'       => $oSdkSort,

));



And my display code (chunk taken out of a CGridView declaration):


'name' => array(

   'name' => 'name',

   'type' => 'html',

   'value' => 'CHtml::link( CHtml::encode( substr( $data->name, 0, 56 ).( strlen( $data->name ) > 72 ? "..." : "" )), array( "/game/view", "id" => $data->game_id) )',

),

Now notice where I use the ‘with’ property to bring in some attributes of the ‘game’ relation, and those function properly when sorting, as you would expect. However, trying to access $data->name gives the error that GameSubmission doesn’t have that attribute, which is true, but the attribute should have been included by the ‘with’ property.

Is there a workaround for this? Does the functionality between CActiveDataProvider and these other classes need to be altered?

Any help is appreciated, thanks!

Don’t know if I’m missing something here but you should try $data->game->name instead.

/Tommy

$data->game->name works but I’ve already queried the game relation using the “with” param in my CDbCriteria, and I’m trying to avoid querying it twice for every row. My point is that CSort is able to grab $data->rel_date (rel_date is a property of Game), but CGridView is apparently unable to grab these relational attributes, when it appears like it should be able to.

Why do you think it will be queried twice? Eager loading will take place because you added with, $data->game->name will access the loaded data.

/Tommy

I checked my Web log route in combination with some profiling calls and my tbl_Game is being queried twice for each row for the same primary key. Is there a way to use something like $data->game->name to explicitly access the fields that should by joined by the "with" param, without re-querying the relation?

Does anyone have any other ideas? This feels more and more like a functionality gap or bug between CActiveDataProvider and CGridView.

In case anyone in the future runs into this or a similar problem, I’ve found using CArrayDataProvider to be a suitable workaround.