You are viewing revision #3 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 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 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 key- If you define a
BELONGS_TO
relation in one model, you probably want an associatedHAS_MANY
relation in its related mode - You probably don't really want
HAS_ONE
ever
Very Helpful
This post was especially helpful in debugging issues with my application's model structure. SJFriedl, very good work.
HAS_ONE = PK, FK
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 -> tbluser.id
user HAS_ONE profile and profile BELONGS_TO user
Please tell me if I'm wrong.
Great article :-)
Confused about schema for profile table
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.
Very helpful
Thanks, this is exactly what I needed to read to solve my problems.
Very useful
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)
LIMIT
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...
Key Point is highlight
I like the key point summary part, which is very helpful for Yii beginners. Thanks a lot.
Has Many with limit
return array( 'posts' => array(self::HAS_MANY, 'Post', 'P_ID','limit'=>'5'), );
Weird example
About the Weird example.
I had seen this way before, but how it possible to Create a user row later. let say, get the status_id, that wwill create the record on Status Table then retrieve on user row added?
Another example of this approach.
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.