As you say, the difference between the two is on which table the foreign key resides. The natural relationship would be
// Album model
function owner() {
return $this->belongsTo('App\User', 'last_edit_by', 'user_id');
}
// User model
function albums() {
return $this->hasMany('App\Album', 'last_edit_by', 'user_id');
}
hasOne is incorrect because "user_id" is not a foreign key, it is the primary key of the users table and "last_edit_by" is the foreign key. And although it works, it is an incorrect description of the relationship.
Hope it makes sense.
http://laravel.com/docs/4.2/eloquent#relationships
PS> By convention, user_id should be renamed "id" on the users table and "last_edit_by" should be renamed "user_id" on the albums table. But I don't want to confuse you further!
jacksoncharles said:
hasOne is incorrect because "user_id" is not a foreign key, it is the primary key of the users table and "last_edit_by" is the foreign key. And although it works, it is an incorrect description of the relationship.
Hope it makes sense.
I think it is beginning to make sense. I guess it leaves me wondering, why does it work? Is it wrong because 'by convention that's not how to do it"? Or is it wrong becase 'eventually this will NOT work, even though it does on this simple example'.
I'll make it right. I definitely don't want to leave it 'wrong' no matter the reason. But I'm trying to understand why its wrong. If I was unwise, and left it with the hasOne defined with the keys switched. Would it eventually break and not work as I built more complex queries? Or would it just become confusing keeping things straight, but if you did keep it straight, it would always work, even though technically wrong?
http://laravel.com/docs/4.2/eloquent#relationships
PS> By convention, user_id should be renamed "id" on the users table and "last_edit_by" should be renamed "user_id" on the albums table. But I don't want to confuse you further!
This is true, and I knew they weren't conventional names. But the database already exists. Is it worth the effort to rename all the database columns (there are many more than these two) to fall in line with convention? Or since the database exists as created by others, should I just leave it and deal with it as is.
I guess I don't know how important convention is in this matter.
I love this question as it brings up an interesting point about laravel. To me, laravel suffers from the same problem that php sometimes has, which is that it allows you to legally do something even though it is not recommended and sometimes ultimately not correct.
Both these relationships are legal but only one is correct in certain situations.
Imagine that you have two models, a User and a Company.
You can say "A user has one company" and conversely you can say "A user belongs to a company".
If you put the foreign key company_id in the users table then the natural relationship is that a user belongs to a company.
However it is legal in laravel to say
public function company()
{
return $this->hasOne('Company', 'id', 'company_id')
}
However, if you do that you will run into this problem
$user = User::find(1);
$company = Company::find(999);
$user->company()->associate($company); // <-- This method does not exist
// the above method does not exist so you try to call save(), which is the correct method for hasOne
$user->company()->save($company); // <-- This method will execute but the result is not what you expect
// in the above save method it will execute this query
// update `companies` set `id` = where `id` = 999
// yes that's right it made the company id an empty value
rickshawhobo said:
I love this question as it brings up an interesting point about laravel. To me, laravel suffers from the same problem that php sometimes has, which is that it allows you to legally do something even though it is not recommended and sometimes ultimately not correct.
Both these relationships are legal but only one is correct in certain situations.
Imagine that you have two models, a User and a Company.
You can say "A user has one company" and conversely you can say "A user belongs to a company".
If you put the foreign key company_id in the users table then the natural relationship is that a user belongs to a company.
However it is legal in laravel to say
public function company() { return $this->hasOne('Company', 'id', 'company_id') }
However, if you do that you will run into this problem
$user = User::find(1); $company = Company::find(999); $user->company()->associate($company); // <-- This method does not exist // the above method does not exist so you try to call save(), which is the correct method for hasOne $user->company()->save($company); // <-- This method will execute but the result is not what you expect // in the above save method it will execute this query // update `companies` set `id` = where `id` = 999 // yes that's right it made the company id an empty value
Thanks rickshawhobo, that makes a bit more sense now. I think I'm seeing what the problem could eventually be. I think I actually did run into that type of problem earlier when I was defining the foreign_key field incorrectly, but I was leaving the 3rd argument blank. I was getting weird issues. And I think your explanation makes me understand why that wasn't working better.
Always better to do it 'right' even if 'not-right' isn't currently producing an error I guess.
Sign in to participate in this thread!
The Laravel portal for problem solving, knowledge sharing and community building.
The community