4

Trying to get a one-to-many relationship working in Laravel 5.4. I've read through the documentation and other resources online and in each instance can't get it working, and various ways I've tried results in different errors.

I have the following three tables:

  • accounts
  • contacts
  • account_contact (pivot table) has the fields: account_id (int/Foreign key), contact_id (int/Foreign key), primary (int), billing (int)

I'm trying to make it so the account can (but not necessarily) have one or more contacts.

My Models are as follows:

accounts

public function contacts()
{
    return $this->hasMany(Contact::class);
}

contact

public function account()
{
    return $this->belongsTo(Account::class)->withPivot('primary', 'billing');      
}

Then say in a controller I attempt:

$account = Account::find($id);
if($account->isEmpty())
    return response()->json(['Account not found.'], 404);
$contact = $account->contacts()->exists();

I get the following error:

(1/1) BadMethodCallException Method contacts does not exist.

Obviously what I'm trying to do is make it so when a contact is made, it can be attached to an Account through the Pivot table. And when getting the Account, I can then, through the Pivot table get the extra Pivot table fields, and the contact(s) that belong to that Account.


Just to clarify a little further, I am trying to use eloquent, using pivots to do the following query, without having to write it out in every instance.

$contacts = DB::table('account_contact')
                    ->select('contact_id', 'primary', 'billing')
                    ->where('account_id', $id)
                    ->get();
$accountContacts = [];
foreach($contacts as $c){
    $accountContact = Contact::find($c->id);
    $accountContacts[] = array( 
                    "id" => $accountContact->id,
                    "sal" => $sal = $accountContact->salutation == null? '' : $accountContact->salutation,
                    "firstName" => $accountContact->first_name,
                    "lastName" => $accountContact->last_name,
    );
}

I was hoping to just be able to do something like $accounts->pivot->contacts and get a name like so: $accounts->pivot->contacts->first_name

Seán McCabe
  • 893
  • 4
  • 23
  • 47

2 Answers2

3

Your relationship is many to many so you need to do this:

accounts

public function contacts()
{
    return $this->belongsToMany(Contact::class)->withPivot('primary', 'billing');
}

contact

public function account()
{
    return $this->belongsToMany(Account::class)->withPivot('primary', 'billing');      
}

Then you should do this via eloquent all the way to avoid the N+1 issue

$account = Account::with("contacts")->where("id", $id)->get();

foreach ($account->contacts as $contact) {
      $accountContacts[] = array( 
            "id" => $accountContact->id,
            "sal" => $sal = $accountContact->salutation == null? '' : 
             $accountContact->salutation,
            "firstName" => $accountContact->first_name,
            "lastName" => $accountContact->last_name,
      );
}
apokryfos
  • 38,771
  • 9
  • 70
  • 114
  • problem is, it is not many-to-many. An account can have many contacts, but a contact cannot belong to many accounts. Would this answer still apply? – Seán McCabe Nov 07 '17 at 22:30
  • 2
    If a contact cannot belong to many accounts then you should have the `account_id` in the contact table and not have the pivot as the pivot does not impose the constraint you've mentioned. This answer applies when you have a pivot. The `Account::with` part would also apply for one to many relationships as well as long as the table structure is appropriate. – apokryfos Nov 07 '17 at 22:35
  • Thanks, that worked. Will just leave it as a many-to-many, as it works either way. – Seán McCabe Nov 07 '17 at 23:39
0

In your account model, make one relationship like this:

public function account_contact()
{
    return $this->belongsToMany('App\Account', 'account_contact', 'account_id', 'contact_id');
}

And then fetch using the function you wrote. I hope it would work. Please try this out and tell me how it goes.

Himanshu Upadhyay
  • 6,558
  • 1
  • 20
  • 33
  • 1
    I will be away from my computer for a while but I will be checking your comments with my phone. If it does not work then please bear with me. I will check for it when I will be back. Hope I won't get any down vote for the help. – Himanshu Upadhyay Nov 07 '17 at 19:52
  • Course not, I appreciate all help given :) Don't expect answers straight away. Will test this now. – Seán McCabe Nov 07 '17 at 19:53
  • Didn't work, still get bad method call, but with account_contact instead of contact as per the updated function name. *Method account_contact does not exist.* – Seán McCabe Nov 07 '17 at 19:56