Saving one to one relation in Laravel

33,405

Solution 1

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.

Solution 2

$user = User::findOrFail(1);
$company = $user->company ?: new Company;
$company->name = 'Test';
$user->company()->save($company);

Solution 3

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. Check out my blog post for more.

Share:
33,405
rap-2-h
Author by

rap-2-h

Laravel enthusiast & Rust artisan. Resume: https://raph.site/en

Updated on July 19, 2022

Comments

  • rap-2-h
    rap-2-h almost 2 years

    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)