Relational Record Problem

I have made a mistake, but I'm not sure what the solution is.

I have a few Relational Objects, lets say Handset, Model, Manufacturer.

A Handset is a record of a specific physical phone device. A model is information about a kind of Handset, like a Treo or iPhone 3G s.

So a Handset has a self::HAS_ONE ModelId reference. A Model has a self::HAS_ONE ManufacturerId reference.

When I list out the Handsets, if I have two Handsets with the same ModelId, I get nulls for the second ModelId. Is this because the Handset to Model relation is HAS_ONE from Handset but not MANY_MANY from Model? Do I need to add a MANY_MANY for Model?

What should I do here?

Hi

No, there couldn't be a MANY_MANY relation from model to handset if you're having a HAS_ONE relation from handset to model, this doesn't work.

If one handset belongs to only one model and the modelID is kept inside the handset table then your relation between handset and model should be BELONGS_TO - i think.

Further you only need to add relations in Yii whether you want to use them with your active records. The relations behind it must be defined in your database schema not in Yii.

Maybe you should post your relations and the code how you read the data for the handsets from the db.

I've created a subset of my objects to demonstrate the problem I'm having.

Here are my table definitions, not very exciting, but enough to present the problem:

CREATE TABLE HandsetModel (

    id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,

    label VARCHAR(25) NOT NULL

) ENGINE=InnoDB;

// edit, I left out the foreign key on first post, by mistake

CREATE TABLE Handset (

    id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,

    label VARCHAR(25) NOT NULL,

    handsetModelId INTEGER UNSIGNED NOT NULL,

    FOREIGN KEY (handsetModelId) REFERENCES HandsetModel(id) ON DELETE CASCADE

) ENGINE=InnoDB;

Here are my two Models:

class Handset extends CActiveRecord

{

       // normal stuff

public function tableName()


{


	return 'Handset';


}





public function rules()


{


	return array(


		array('label','length','max'=>25),


		array('label, handsetModelId', 'required'),


		array('handsetModelId', 'numerical', 'integerOnly'=>true),


	);


}





public function relations()


{


	return array(

            'handsetModel'=>array(self::HAS_ONE, 'HandsetModel', 'id'),

	);


}

}

class HandsetModel extends CActiveRecord

{

        // normal stuff

public function tableName()


{


	return 'HandsetModel';


}





public function rules()


{


	return array(


		array('label','length','max'=>25),


		array('label', 'required'),


	);


}





public function relations()


{


	return array(


	);


}

}

I created some data by just adding some site controller actions. Here is the code,

public function actionGenerateModels()

{

          $handsetModel=new HandsetModel();

          $handsetModel->setAttribute('label', 'Treo Pro');

          $handsetModel->save();

 

          $handsetModel=new HandsetModel();

          $handsetModel->setAttribute('label', 'iPhone');

          $handsetModel->save();

}

public function actionGenerateHandsets()

{

        $handsetModels=HandsetModel::model()->findAll();

        foreach ($handsetModels as $handsetModel)

        {

            for($i = 0; $i < 3; ++$i)

            {

                $handset=new Handset();

                $handset->setAttribute('label', $handsetModel->label . ' ' . $i);

                $handset->setAttribute('handsetModelId', $handsetModel->id);

                $handset->save();

            }

        }

}

Then on my index, I just show the list of Handsets,

public function actionIndex()

{

        $handsets=Handset::model()->with('handsetModel')->findAll();

$this-&gt;render(&#039;index&#039;, array(&#039;handsets&#039;=&gt;$handsets));

}

And here is my index,

<table border=1 width=500px>

<tr><td align=center>Handset</td><td align=center>Model</td></tr>

<?php foreach($handsets as $handset): ?>

<tr>

<td><?php echo $handset->label; ?></td><td><?php echo $handset->handsetModel->label; ?></td>

</tr>

<?php endforeach; ?>

</table>

My database looks like this:

id label             handsetModelId

1 Treo Pro 0     1

2 Treo Pro 1     1

3 Treo Pro 2     1

4 iPhone 0     2

5 iPhone 1     2

6 iPhone 2     2

But when I run the app, my index looks like this

id Handset Model        ModelId

1 Treo Pro 0 Treo Pro 1

2 Treo Pro 1 iPhone 2

3 Treo Pro 2

4 iPhone 0

5 iPhone 1

6 iPhone 2

In your Headset model you can do this:

public function relations(){

    return array(

      'headsetModel'=>array(self::BELONGS_TO,'HandsetModel','andsetModelId'),

  );

}

Then, in your view, you can access the headsetmodel like this:

$headset->headsetModel;

Hope this helps you!

Aha! Well done! I didn't realize is wast BELONGS_TO, instead of HAS_ONE.

Thank you, +1 for you.

Thanks… but yoshi points you something similar, so I think he deserves a +1 too… ;)