Why does the foreign key in a hasOne relationship need to be in the referenced table?

Viewed 1032

Why does Laravel’s Eloquent insist that the foreign key in a hasOne relationship must be in the referenced table and not in the parent table?

I'm asking for general understanding / enrichment.

eg, from the Laravel docs: If a User has one Phone, the Phone model is expected to have a user_id foreign key.

This seems like more work for the database to do: to go and find the user_id in the Phones table, versus a phone_id already being present on the User model.

I'm assuming these three reasons below all apply - are there any other reasons to structure it in this way?

  • It can utilise logic already written for looking up has-many relationships (where it’s obvious why it needs to be this way).
  • The relationship can easily be ‘migrated’ to a has-many relationship.
  • It guarantees that wherever a relationship exists, the Phone model also does in fact exist. (Otherwise, a phone_id in the User model could potentially point to a non-existent entry in the Phones table.)
2 Answers

This seems like more work for the database to do: to go and find the user_id in the Phones table, versus a phone_id already being present on the User model.

What you mention here is what is known as a BelongsTo relationship, and is in fact the inverse of a HasOne or HasMany. This means that if a User has one or many Phone(s), the Phone automatically belongs to a User via the user_id foreign key. This also means that a Phone will only ever belong to one User.

You are quite correct in the similarities between HasOne and HasMany as they use foreign keys in exactly the same way. In fact, the only real difference in Eloquent is that for a HasOne, it returns the first match in the referenced table, rather than all available matches as with a HasMany.

Note that your third point is not quite correct, as it is just as possible that a user_id in the phones table does not point to an existing entry in users, unless there are constraints in place in your db that enforce your foreign key to point to an existing entry.

Related