Laravel 5.2 Using Associate to Update a BelongsTo Relationship

10,993

You must retrieve or create new profile entity first and put it in $profile. Also, you have One-to-one relation here, so you should save your user's profile like this:

$user->profile()->save($profile);

Share:
10,993
mtpultz
Author by

mtpultz

Life is all about managing your time effectively and finding a balance between work and play. In development, I found the balance between the front- and back-end work provides a lot of job satisfaction and diversity of work. Through my work experience as a full-stack developer I have a well-balanced set of skills for web application development, which include a proficiency to learn new languages and frameworks on demand, ability to communicate not only with other developers but with customers, production of well-documented and maintainable code that include automated tests, experience with deployment and clouds services like Digital Ocean and CircleCI, as well as familiarity with Linux, command-line, virtual environments (Vagrant), containers (Docker), and version control (Git).

Updated on June 23, 2022

Comments

  • mtpultz
    mtpultz almost 2 years

    I'm using Route Model Binding to get a User instance then update it if validation passes, and then update the associated belongs to relationship between User and Profile, but I keep getting an error. The update occurs on the User, but fails on updating the Profile. From what I've understood from the docs this appears to be correct. I can access Profile data using $user->profile so the relationship appears to be okay in the User and UserProfile models.

    Can anyone see what is wrong with this controller action:

    public function update(Request $request, User $user)
    {
        $this->validate($request, [
            'username'     => 'required|max:32|unique:users',
            'email'        => 'required|email|max:128|unique:users',
            'first_name'   => 'required',
            'last_name'    => 'required',
            'phone_number' => 'regex:/^([0-9\s\-\+\(\)\.]*)$/',
        ]);
    
        $user->update($request->all());
    
        $profile = new UserProfile($request->all());
        // Also tried:
        //$profile = UserProfile::where(['user_id' => $user->id])->first();
    
        $user->profile()->associate($profile);
        $user->save();
    
        return response()->json([
            'message' => trans('user.updated'),
        ]);
    }
    

    Error

    BadMethodCallException in Builder.php line 2161:
    Call to undefined method Illuminate\Database\Query\Builder::associate()
    

    User Model Relationships

    /**
     * A user has-one profile.
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function profile()
    {
        return $this->hasOne('App\UserProfile');
    }
    

    UserProfile Model Relationship

    /**
     * A user profile belongs to a user.
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function user()
    {
        return $this->belongsTo('App\User');
    }
    

    Solution

    $user->fill($request->all())->save();
    
    $profile = UserProfile::where('user_id', $user->id)->first();
    $profile->fill($request->all());
    $user->profile()->save($profile);
    
  • mtpultz
    mtpultz about 8 years
    Hi, I updated my question with the addition of new UserProfile($request->all());, but I still seem to be getting the same error.
  • Alexey Mezenin
    Alexey Mezenin about 8 years
    Here, your profile and user should have an ID. Try to retrieve existing profile first: $profile = Profile::where('user_id', $user->id)->first()
  • Alexey Mezenin
    Alexey Mezenin about 8 years
    You've updated the code and it seems you have On-to-one relation, so you should save it with: $user->profile()->save($profile);
  • mtpultz
    mtpultz about 8 years
    Hi, this appears to create a new record in Profile when one already exists.
  • mtpultz
    mtpultz about 8 years
    Wasn't there a fill() for models at some point so I could go $profile = Profile::where('user_id', $user->id)->first(); then $profile->fill($request->all()); and then $user->profile()->save($profile)', but instead it seems you have to $profile->first_name = 'test' etc then save.
  • Alexey Mezenin
    Alexey Mezenin about 8 years
    Yes, you can use mass assigment. You should fill the $fillable array first: laravel.com/docs/5.1/eloquent#mass-assignment
  • mtpultz
    mtpultz about 8 years
    Thanks, I've updated my question with the solution you've indicated.