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:
BELONGS_TO is where this model owns the linking fieldBELONGS_TO references the related model's primary keyHAS_ONE/HAS_MANY is where the related model owns the linking fieldHAS_ONE/HAS_MANY reference this model's primary keyBELONGS_TO relation in one model, you probably want an associated HAS_MANY relation in its related modeHAS_ONE ever
Total 6 comments
sorry my english is bad :(
now.. a few Relations, given how by difference Relations to limit
exp;
parent = HAS_MANY = limit 5
children = BELONGS_TO = limit 4
notes = HAS_MANY = limit 10
etc...
Short, concise, clear and to the point. I like it! :) The mentioned points should definitely go into the official guide. AFAIK its not there and it should (the difference between belongs_to and has_one)
Thanks, this is exactly what I needed to read to solve my problems.
Although it's not explicit in the article, I would think that the relation from profile to user would be an identifying relation. Yet the schema has the relation as non-identifying (a profile can exist without a user). And it allows more than one profile per user. The Yii logic overlaid upon the schema prevents this and appears to make the profile table's id column superflous.
I think ManInTheBox was saying the same in #5030.
As my point of view, HAS_ONE relation stands for column which is PK, FK in referenced table. Example:
tbl_profile.user_id (PK, FK) references -> tbl_user.id
user HAS_ONE profile and profile BELONGS_TO user
Please tell me if I'm wrong. Great article :-)
This post was especially helpful in debugging issues with my application's model structure. SJFriedl, very good work.
Leave a comment
Please login to leave your comment.