pt844931's avatar

how is it possible to get hasmany relationship in resource collection

Hello, i build an api where i wan't to show all seasons with the inculded tracks, the tracks are given to the season via hasmany relation. i already build an resource where i have all of them saved, but now i want to make an pagination, i already looked in documentation at: https://laravel.com/docs/8.x/eloquent-resources#data-wrapping-and-pagination but its only working for single seasons and they not include the related tracks. so is there a possibility to get the seasons and the related tracks?

My Routes are like this:

Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
    return $request->user();
});
Route::get('/tracks', [ApiTracksController::class, 'index']);
Route::get('/topics', [ApiTopicsController::class, 'index']);
Route::get('/seasons', [ApiSeasonController::class, 'index']);
Route::get('/season/{id}', [ApiSeasonController::class, 'singleSeason']);
Route::get('/seasons/{id}/tracks', [ApiSeasonController::class, 'trackShow']);
Route::get('/speakers', [ApiSpeakerController::class, 'index']);
Route::get('/seasons/all', function () {
        return new \App\Http\Resources\Season(SeasonResource::paginate(1));
});

The Coleection is looks like this:

class Season extends ResourceCollection
{
    /**
     * Transform the resource collection into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
     */
    public function toArray($request)
    {
        return [
            'data' => $this->collection,
            'links' => [
                'self' => 'link-value'
            ]
        ];
    }
}

And my single Resources for Track and Season are like this: SeasonResource

class SeasonResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  Request  $request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'description' => $this->description,
            'thumbnail' => $this->thumbnail,
            'tracks' => TrackResource::collection($this->whenLoaded('tracks')),
        ];
    }
}

TrackResource:

class TrackResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  Request  $request
     * @return array
     */
    public function toArray($request)
    {
    return [
            'id' => $this->id,
            'title' => $this->title,
            'description' => $this->description,
            'data' => $this->data,
            'season_id' => $this->season_id,
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
            'topics' => TopicResource::collection($this->topics),
            'speakers' => SpeakerResource::collection($this->speakers)
        ];
    }
}

If somebody knows how to do that would really appreciate :) Thank you

1 like
2 replies
Nakov's avatar
Nakov
Best Answer
Level 73

You need to load the relationship data since you are trying to conditionally load the resource. Your naming is correct so instead of passing the resource you can pass the model with its data, for example

Route::get('/seasons/all', function () {
        return new \App\Http\Resources\Season(App\Models\Season::with("tracks.topic", "tracks.speakers")->paginate(1));
});

As an example. Sorry my formatting might be bad as I am typing from a phone, but I hope it’ll give you a direction. 🙂

https://laravel.com/docs/8.x/eloquent-resources

pt844931's avatar

@Nakov Thank you very much, works now perfectly fine, didnt mentioned the with method, i already used it for something else :')

Please or to participate in this conversation.