It's very common to see new Yii users confusing the relations
BELONGS_TO, and getting it wrong means you won't get proper values back. And though we'll talk about
HAS_MANY as well, we're specifically omitting the
MANY_MANY relation because it's a whole different animal.
HAS_ONE are about linking two models together, and sound like the same thing, but they link in essentially opposite directions. Let's illustrate with three simple tables, each of which has a primary key (
id), and a number of linking fields (
user_id) that reference the User table.
USER table - id - name POST table - id - user_id REFERENCES User.id - content PROFILE table - id - user_id REFERENCES User.id - profile_info
KEY POINT: A
BELONGS_TO relation says that a field in this model points to the primary key in another model; in this case, the current model owns the linking field.
KEY POINT: A
HAS_ONE relation says that some other model has a linking field pointing to this model's primary key; in this case, the related model owns the linking field.
We can thik that a PARENT table will be the one that doesn't have a foreign key, and a CHILD table as the one who "depends" on the parent table, that is, it has a foreign key.
Given that, a CHILD BELONGS_TO a PARENT and a PARENT HAS_ONE CHILD.
Let's put these in context (numbered for reference)
// Post model relations 1. 'user' => array(self::BELONGS_TO, 'User', 'user_id'), // Post belongs_to a user, because it is a child table. // Profile model relations 2. 'user' => array(self::BELONGS_TO, 'User', 'user_id'), // Profile belongs_to a user, because it is a child table. // User model relations 3. 'posts' => array(self::HAS_MANY, 'Post', 'user_id'), // User has_many posts, because User is a parent table. 4. 'profile' => array(self::HAS_ONE, 'Profile', 'user_id'), // User has_one profile, because User is a parent table.
Relations 1 has the linking field
user_id in this model, pointing to the primary key of the related model
User. Likewise with relation #2.
Relations 3 and 4 are essentially the same thing as each other: the linking field
user_id is not in this model, but in the related model, and the primary key involved is in this model (
User). The difference is that
HAS_MANY returns an array of possibly multiple objects, while
HAS_ONE returns a single object.
HAS_ONE is just a special case of
HAS_MANY, and the circumstances where
HAS_ONE makes sense are far more limited than
USER table - id - name - status_id REFERENCES status.id STATUS table - id - name
Here one would think in human terms that a USER HAS_ONE STATUS. But that doesn't work. As you see, the USER is in fact a "child" table of STATUS, because it is referencing it, it depends on it. So the relations would be:
// User model relations 1. 'status' => array(self::BELONGS_TO, 'Status', 'status_id'), // User belongs_to a status, because it is a child table. // Status model relations 2. 'users' => array(self::HAS_MANY, 'User', 'status_id'), // Status has_many users, because it is a parent table.
Some points to remember:
BELONGS_TOis where this model owns the linking field
BELONGS_TOreferences the related model's primary key
HAS_MANYis where the related model owns the linking field
HAS_MANYreference this model's primary key
BELONGS_TOrelation in one model, you probably want an associated
HAS_MANYrelation in its related mode