You are viewing revision #6 of this wiki article.
This version may not be up to date with the latest version.
You may want to view the differences to the latest version or see the changes made in this revision.
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_id REFERENCES User.id
- user_id REFERENCES User.id
**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:
- When defining one of these relations, you don't ever name the primary key; Yii figures it out from the DB schema
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
- If you define a
BELONGS_TOrelation in one model, you probably want an associated
HAS_MANYrelation in its related mode
- You probably don't really want