28

I'm not quite sure if I understand the associate method in Laravel. I understand the idea, but I can't seem to get it to work.

With this (distilled) code:

class User
{

    public function customer()
    {
        return $this->hasOne('Customer');
    }

}

class Customer
{

    public function user()
    {
        return $this->belongsTo('User');
    }

}

$user = new User($data);
$customer = new Customer($customerData);

$user->customer()->associate($customer);

I get a Call to undefined method Illuminate\Database\Query\Builder::associate() when I try to run this.

From what I can read, I do it exactly as is stated in the docs.

What am I doing wrong?

Matthijn
  • 3,126
  • 9
  • 46
  • 69

3 Answers3

52

I have to admit that when I first started using Laravel the relationships where the part that I had to consistently refer back to the docs for and even then in some cases I didn't quite get it right.

To help you along, associate() is used to update a belongsTo() relationship. Looking at your code, the returned class from $user->customer() is a hasOne relationship class and will not have the associate method on it.

If you were to do it the other way round.

$user = new User($data);
$customer = new Customer($customerData);

$customer->user()->associate($user);
$customer->save();

It would work as $customer->user() is a belongsTo relationship.

To do this the other way round you would first save the user model and then save the customer model to it like:

$user = new User($data);
$user->save();

$customer = new Customer($customerData);
$user->customer()->save($customer);

Edit: It may not be necessary to save the user model first but I've just always done that, not sure why.

David Barker
  • 14,484
  • 3
  • 48
  • 77
  • 1
    Yes, your first thing seems to work correctly. I think it's kinda odd that it has to work that way around. Anyhoe, thanks. And so that you may learn something new: $user->push(); saves the user and all it's relationships. – Matthijn Oct 02 '14 at 12:55
  • 1
    I noticed that we need to do `$customer->save()` after `->associate($something)` – vozaldi May 29 '19 at 01:33
  • in other words, User class hosts/has the Customer. So that we can associate/disassociate the user to/off a given customer like `$customer->user()->associate($user)` or `$customer->user()->associate()`, next to `$customer->save()` – CodeToLife Feb 10 '21 at 00:53
  • 1
    You can also directly save after the association like this `$customer->user()->associate($user)->save();` – Gkiokan Oct 17 '21 at 21:42
10

As I understand it, ->associate() can onyl be called on a BelongsTo relationship. So, in your example, you could do $customer->user()->associate($user). However, in order to 'associate' a Has* relationship you use ->save(), so your code should be $user->customer()->save($customer)

alexrussell
  • 13,856
  • 5
  • 38
  • 49
  • having same problem. but on belongToMany() relation. how could I fix this? thanks – aleXela Nov 29 '16 at 21:30
  • 2
    For many-to-many methods (see docs https://laravel.com/docs/5.3/eloquent-relationships#updating-many-to-many-relationships) you use `->attach()` and `->detach()`. E.g. `$post->tags()->attach($tag);` Now, officially, the attach and detach method only accept IDs, but when I tested this some time ago on 4.x, you could pass actual models in. That may have changed for 5.x. – alexrussell Dec 01 '16 at 09:57
  • this kinda working. but its asking for an array, and i'm getting object instead. – aleXela Dec 01 '16 at 21:18
  • 1
    I think your best course of action here is to ask a new question specific to your problem. Include the version of Laravel you are using and any relevant code and I'm sure you will get the help you need. – alexrussell Dec 05 '16 at 14:25
0

just add ->save() to the end.

$user->customer()->associate($customer)->save();

mikoop
  • 1,981
  • 1
  • 18
  • 18