Reputation: 31948
A User
has one (or zero) Company
, and a Company
belongs to one and only one User
. I try to save a company for a user but it adds a new entry in database every time I re-trigger the save method. It's a one to one relation, so I though save
method on User
.
So Company
has one method user()
:
public function user() {
return $this->belongsTo(User::class, 'user_id');
}
And User
has one method company()
:
public function company() {
return $this->hasOne(Company::class, 'user_id');
}
I'm trying to save (so create or update) a user's company like this (in a Controller):
$company = new Company();
$company->name = 'Test';
User::findOrFail(1)->company()->save($company);
First time I run this code it creates the entry in database (OK), but second time it adds a new entry for the same user (Not OK). I thought it will only update the database entry.
Is it a glitch (or something I don't understand in one to one relation) in Laravel or am I doing something wrong? (I think and hope it's the second purpose)
Upvotes: 26
Views: 45719
Reputation: 29019
I'm trying to save (so create or update) a user's company
You can do exactly that with the updateOrCreate method:
User::findOrFail(1)->company()->updateOrCreate([],['name' => 'xyz']);
The first parameter of updateOrCreate
is an empty array, because the companies id
is determined by the hasOne
relationship $user->company()
.
And by the way, I would recommend not using an auto-increment id field in a hasOne
relationship. If you set user_id
as primary in your company table, its technically not possible to create duplicate company rows for one user.
Upvotes: 18
Reputation: 3825
$user = User::findOrFail(1);
$company = $user->company ?: new Company;
$company->name = 'Test';
$user->company()->save($company);
Upvotes: 31
Reputation: 1074
Creating and updating need to treat differently. So check the existence of company attribute first.
$user = User::with('company')->findOrFail(1);
if ($user->company === null)
{
$company = new Company(['name' => 'Test']);
$user->company()->save($company);
}
else
{
$user->company->update(['name' => 'Test']);
}
Note that hasOne()
does not guarantee that you will have one-to-one relationship, it just telling Eloquent how to create query. It works even you have multiple Company
refer to same User
, in such case when you call $user->company
you will get first Company
in the result data set from database.
Upvotes: 41