fluentd's avatar

Accessing data from a Collection

I currently have two models setup Family and Contact. Both have relationships and I am able to access the collection of Family and Associated Contacts via:

$families = Family::with('contacts')->get();

the following worked and is pulling all families and relationship of contacts for each, but now I am not really sure how to use the array of arrays to display data in my table where it has both family and contact information in the same row.

My thought was that I would be able to access a family contact by using the following:

{{ $family->contacts->first_name }}

in my foreach

@foreach ($families as $family)

but instead I am getting an error:

Undefined property: Illuminate\Database\Eloquent\Collection::$first_name 
(View: D:\Google Drive\Development\billing\resources\views\families\indexFamilies.blade.php)

What am I missing here?

0 likes
13 replies
tkjaergaard's avatar

It all comes down to the type of relationship you have defined on the models.

What you're trying to do is if it's a One to One relationship, meaning that a Family has only one Contact, which seems not to be the case when you're naming it "contacts".

This means that it's most likely a One to Many relationship, meaning that a Family can have many Contacts. the contacts is property an array of objects.

@foreach($families as $family)
    echo $family->contacts[0]->first_name
@endforeach

The above code should print out the first name of the first Contact for a Family.

You can read more about the various relationship types in the docs: http://laravel.com/docs/5.0/eloquent#relationships

1 like
calvinchoy's avatar

I think you need to make another loop to go through the contacts you received using:

$family->contacts

    @foreach($family->contacts as $contact)
        {{$contact->first_name}}
    @endforeach

Something like that I think.

fluentd's avatar

Can I do a

@foreach ($families as $family && $family->contacts as $contact)

Maybe that would work?

@tkjaergaard I have my relationships setup

public function family()
{
    return $this->belongsTo('App\Family');
}   

public function contacts()
{
    return $this->hasMany('App\Contact');
}
fluentd's avatar

Just tried

@foreach ($families as $family && $family->contacts as $contact)

and that shot me a FatalError

FatalErrorException in 11fd1626f38346f2c90c98950ad0c7f0 line 44:
syntax error, unexpected '&&' (T_BOOLEAN_AND), expecting ')'
fluentd's avatar

Im still getting a

FatalErrorException in 11fd1626f38346f2c90c98950ad0c7f0 line 78:
Call to undefined method Illuminate\Database\Eloquent\Collection::contact()

I don't know why I am having such trouble with Eloquent. I have gone through all the fundamentals but I feel there is a lot of explanation and examples left out. The Laravel documentation is pretty bare as well and almost zero examples, really wish it was like the jquery documentation.

Snapey's avatar

you are probably not far off. you need to visualise the nested arrangement of contacts within each family. Just try returning your first families query from your controller instead of make->view. you will get a Json response. of you have trouble reading that, download a browser plugin for formatting Json. it's worth having this installed anyway.

Snapey's avatar

@fluentd what I am saying is, do this in your controller

$families = Family::with('contacts')->get();
return $families;

you will then see the structure but you might need a Json plugin to your browser to make it really clear.

The one I use in Chrome is called JSONView

Snapey's avatar

A working example from my users index page where each user can have many systems;

//UsersController
        $users = User::with('systems')->get();
        return view('users.index')->with(compact('users'));

and then in the view using blade

//index.blade.php
<table class="table">
                        <thead>
                            <th>Name</th>
                            <th>Email</th>
                            <th>Systems</th>
                        </thead>
                        <tbody>
                    @foreach($users as $user)
                        <tr>
                            <td><a href="/admin/users/{!!$user->id!!}/edit">{{$user->name}}</td>
                            <td>{{$user->email}}</td>
                            <td>
                                @foreach($user->systems as $system)
                                    {{$system->name}},
                                @endforeach
                            </td>
                        </tr>
                    @endforeach
                        </tbody>
                    </table>
1 like
fluentd's avatar

I appreciate everyone's suggestions and help, I was able to get this working. I also added a constraint to the Eager loading.

$families = Family::with(['contacts' => function($query)
    {
        $query->where('is_primary', 1);
    }])->get();

I am still not 100% sure this is the correct way to do it. I would have liked to use a Query Scope from the Contact Model but was not able to get that working.

Below is the Query Scope:

public function scopePrimary($query){
    return $query->where('is_primary', 1);
}
davorminchorov's avatar

Did you try something like this?

    $families = Family::with('contacts')->primary()->get();

Please or to participate in this conversation.