Question: CActiveRecord - Relations to other model via non-primary key ?

Hello, everyone…

I have a homework that required me to retrieve data via relational models. Here’s the simplified models that i have:

Model1 attributes are:

  • id

  • username

  • member_number

Model2 attributes are:

  • id

  • member_number

  • start_date

  • expired_date

My teacher ask me to retrieve both start_date and expired_date values based on member_number. So, i put this relation in Model1:


public function relations()

{

	return array(

		'mn'=>array(self::BELONGS_TO, 'Model2', 'member_number'),

	);

}

However when i try this:


echo Model1::model()->findByPk(1)->mn->start_date;

it returned nothing.

A friend told me that the relation is invalid, since i am using member_number as foreign key which it’s not the primary key in Model2.

So, what do i have to do from this point? What kind of relation in Model1 should i use?

Thanks in advance for advices.

  1. relation should be HAS_ONE not BELONGS_TO, please refer to this wiki article;

  2. why not make member_number in model2 as primary key?

Hello, thanks for fast reply.

  1. I’m studying it now. Thanks for the link.

  2. I can’t do nothing regards the model since the database structure is given, and no modifications allowed.

Please understand that i’m just studying php and Yii for few weeks. Thanks.

EDIT:

After several googling and trial-errors, i have managed to make it work, by changing Model1’s relation to:


public function relations()

{

        return array(

                'mn'=>array(self::HAS_ONE, 'Model2', '', 'on'=>'mn.member_number=t.member_number'),

        );

}



It works, yes. But i’m still have no idea of what happened here. :unsure:

i’m new here too, impressive already for a starter of weeks. good job

You may see you requests directly at your page.

I usually add these lines to my config file:


'db'=>array(

your params,

'enableProfiling'=>true,

'enableParamLogging'=>true,

)




        	'routes'=>array(

your params,

            	array(

                	'class'=>'CWebLogRoute',

                	'levels'=>'error, warning',

            	),

            	array(

                	'class'=>'CProfileLogRoute',

            	),

        	)



And one more notice (for other people finding this topic), this solution:


public function relations()

{

        return array(

                'mn'=>array(self::HAS_ONE, 'Model2', '', 'on'=>'mn.member_number=t.member_number'),

        );

}

will work with eager loading only.