Relations: BELONGS_TO versus HAS_ONE

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

« previous (#3)next (#6) »

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 (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