Search code examples
phplaravelpivot-tablelaravel-6laravel-resource

Trying to return pivot data in Resource Laravel


I am trying to return pivot data to a resource. The pivot table works, I can add and remove entrys like expected, but I am not able to get the user_id returned in ActivityResource... In the Laravel Documentation it looks so easy, am I missing something?

// Activity.php
class Activity extends Model
{
    public function members()
    {
        return $this->belongsToMany('App\User', 'activity_user', 'user_id', 'activity_id')->withPivot('activity_id','user_id')->withTimestamps();
    }
}
// User.php
class User extends Authenticatable
{
    public function joinedactivities()
    {
        return $this->belongsToMany('App\Activity');
    }
}

In my ActivityController I want to return a newly created ActivityResource with 'eager-loaded' relationship

// ActivityController 
public function show($id)
{
    $activity = Activity::with('members')->findOrFail($id);

    /* foreach ($activity->members as $user) {
        echo $user->id . " "; // With this I can actually see the right ids
    }
    return;*/

    return new ActivityResource($activity);
}

ActivityResource:

public function toArray($request)
{
    return [
        'id' => $this->id,
        'title' => $this->title,
        'attendees' => $this->whenPivotLoaded('activity_user', function () {
            return $this->pivot->user_id;
        }),
    ];
}

I dont get any errors instead the attendees field is just not returned. I tried so many things, struggeling with that. Help very appreciated. I am using Laravel 6.


Solution

  • ->withPivot('activity_id','user_id') is not needed. Those fields will appear on your relation object no matter what. For the resource, I think you can do the following:

    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            // If the relation 'members' is loaded, get an array of user ids otherwise, return null
            'attendees' => $this->relationLoaded('members') ? $this->members->pluck('pivot.user_id')->unique()->all() : null
        ];
    }
    

    The main problem is the relationship is a Many to Many, meaning there's more than 1 pivot. With this solution, your object will look like this.

    {
        id: 3,
        title: 'A Title',
        attendees: [
            1,
            2,
            3,
        ],
    }
    

    If you want the ids concatenated in a single string like in your commented foreach, replace all() by join(' ')

    // If the relation 'members' is loaded, get an string of user ids otherwise, return null
    'attendees' => $this->relationLoaded('members') ? $this->members->pluck('pivot.user_id')->unique()->join(' ') : null
    
    {
        id: 3,
        title: 'A Title',
        attendees: '1 2 3',
    }