Seán McCabe
Seán McCabe

Reputation: 911

Laravel One-to-many relationship

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:

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

Upvotes: 4

Views: 1940

Answers (2)

apokryfos
apokryfos

Reputation: 40673

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,
      );
}

Upvotes: 3

Himanshu Upadhyay
Himanshu Upadhyay

Reputation: 6565

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.

Upvotes: 0

Related Questions