Michele Della Mea
Michele Della Mea

Reputation: 1002

how to retrieve nested values of a specific column in many to many relationships with laravel

I created a resource MeetingResource.php that should return all the meeting data with an API call.

This is the code of the main function of that resource:

public function toArray($request)
{
    return [
        'id' => $this->id,
        'room_id' => $this->room_id,
        'description' => $this->description,
        'participants' => $this->users[0]['name'] . " " . $this->users[0]['surname'], //here
        'date' => $this->date,
        'start' => $this->start,
        'end' => $this->end,
        'is_active' => $this->is_active
    ];
}

I have a problem with the element participants because it returns only the first participant, but I need every participant in the format above.

The relationship between table users and table meetings is many to many.

This is the relationship in meeting.php model:

public function users()
{
    return $this->belongsToMany('App\User');
}

This is the relationship in user.php model:

public function meetings()
{
    return $this->belongsToMany('App\Meeting');
}

How can I retrieve every user (participant) that participate in a meeting?

Upvotes: 1

Views: 56

Answers (4)

Muhammed ElFeqy
Muhammed ElFeqy

Reputation: 11

you can create another resource for users, let's say UsersResource.

therefore, you can now use it to get a collection of users, but first, you should make some changes in the UsersResource resource like this:

public function toArray($request)
{
    return array_merge(parent::toArray($request), 
    [
       // you can change the attribute name, it's up to you
       'full_name' => $this->name . ' ' . $this->surname
    ]);
}

now you'll have a new attribute that concatenates the participant's name as you want.

in the MeetingResource you have to change the participants attribute as follows:

public function toArray($request)
{
    return [
        'id' => $this->id,
        'room_id' => $this->room_id,
        'description' => $this->description,
        'participants' => UsersResource::collection($this->users),
        'date' => $this->date,
        'start' => $this->start,
        'end' => $this->end,
        'is_active' => $this->is_active
    ];
}

Upvotes: 0

Donkarnash
Donkarnash

Reputation: 12845

You can map over the users to get the name and surname

public function toArray($request)
{
    return [
        'id' => $this->id,
        'room_id' => $this->room_id,
        'description' => $this->description,
        'participants' => $this->users->map(function($user){
                return $user->name . " " . $user->surname;
            })->values()->all(), //here
        'date' => $this->date,
        'start' => $this->start,
        'end' => $this->end,
        'is_active' => $this->is_active
    ];
}

Upvotes: 2

Alex Mac
Alex Mac

Reputation: 923

Though I would use a transformer over this function. You need to utilize your users relationship. For example, to return a collection of the relationship you will use $meeting->users and if you want to extend the query that can be returned through the relationship you can this. $meeting->users()->where('active', true)->get() which will also return a collection however the $meeting->users() returns a Query Builder instance.

public function toArray($request)
{
    return [
        'id' => $this->id,
        'room_id' => $this->room_id,
        'description' => $this->description,
        'participants' => $this->users->only(['name', 'surname']),
        'date' => $this->date,
        'start' => $this->start,
        'end' => $this->end,
        'is_active' => $this->is_active
    ];
}

You can also eager load the relationship by adding the with() to the relationship like...

Class Meeting 
{
    /**
     * The relationships that should always be loaded.
     *
     * @var array
     */
    protected $with = ['users'];

    public function users()
    {
       return $this->belongsToMany('App\User');
    }

}

or in a controller you may do something like...

Class MeetingController extends Controller 
{
    public function index(Request $request) 
    {

        // eager loading users and potentially other relationships
        $meetings = Meeting::where('active', true)->with(['users'])->get();

        return view('meetings.index', compact('meetings'));
    }
}

Upvotes: 0

miken32
miken32

Reputation: 42700

If all you want is the names, just loop through each participant and add it to an array. Pass the array into the returned value.

public function toArray($request)
{
    foreach ($this->users as $user) {
        $participants[] = "$user[name] $user[surname]";
    }
    return [
        'id' => $this->id,
        'room_id' => $this->room_id,
        'description' => $this->description,
        'participants' => $participants
        'date' => $this->date,
        'start' => $this->start,
        'end' => $this->end,
        'is_active' => $this->is_active
    ];
}

Upvotes: 1

Related Questions