Relations: BELONGS_TO versus HAS_ONE

You are viewing revision #2 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.

next (#3) »

It's very common to see new Yii users confusing the relations HAS_ONE and 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.

Both BELONGS_TO and 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 of 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.

Let's put these in context (numbered for reference)

// Post model relations
1.   'user'    => array(self::BELONGS_TO, 'User',    'user_id'),

// Profile model relations
2.   'user'    => array(self::BELONGS_TO, 'User',    'user_id'),

// User model relations
3.   'posts'   => array(self::HAS_MANY,   'Post',    'user_id'),
4.   'profile' => array(self::HAS_ONE,    'Profile', 'user_id'),

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 HAS_MANY and BELONGS_TO.

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_TO is where this model owns the linking field
  • BELONGS_TO references the related model's primary key
  • HAS_ONE/HAS_MANY is where the related model owns the linking field
  • HAS_ONE/HAS_MANY reference this model's primary key
  • If you define a BELONGS_TO relation in one model, you probably want an associated HAS_MANY relation in its related mode
  • You probably don't really want HAS_ONE ever