Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Davva's avatar
Level 10

Using Fractal package with nested collections not working

Hi I am writing an api for a booking system, in which I want to implement the Fractal package, using transformers before sending it as json output.

Overview

Members can book yoga classes from a schedule of classes. The models are:

  • ScheduleItem: a single bookable yoga class in a schedule
  • Booking: a booking made for a specific yoga class by a member

Relationships:

  • A ScheduleItem has many Booking(s)
  • A Booking belongs to a ScheduleItem

The problem

When I try to output the nested collection of data using Fractal (all ScheduleItem(s) with their Booking(s)), I just get an empty collection. If I bypass Fractal and the transformers, and simply diedump the dataset from Eloquent, the bookings are there. So I guess something is not properly setup with Fractal and/or the transformers.

I use Eloquent to fetch all ScheduleItem(s) while eager-loading all Booking(s):

$scheduleItems = ScheduleItem::with( 'bookings' )->get();

(Simplified) models with eloquent relationships

class ScheduleItem extends BaseModel {
    public function bookings()
    {
        return $this->hasMany( 'App\Booking' );
    }
}

class Booking extends BaseModel {
    public function scheduleItem()
    {
        return $this->belongsTo( 'App\ScheduleItem' );
    }
}

The eloquent query

$scheduleItems = ScheduleItem::with( 'bookings' )->get();
dd($scheduleItems);

The snippet above will give something like this (shortened for brevity):

[
    {
        "id": "0a2b583e-732c-42b4-ae18-a2ae915816b8",
        ...
        "bookings": [
            {
                "id": "0ad5b807-ec8b-456b-8246-4497d380e95e",
                "schedule_item_id": "0a2b583e-732c-42b4-ae18-a2ae915816b8",
                ...
            },
            {
                "id": "56750e85-9d82-44cc-be5e-d1d00f31036c",
                "schedule_item_id": "0a2b583e-732c-42b4-ae18-a2ae915816b8",
                ...
            },
            ...
        ]
    },
    ...
]

If I pass the eloquent object through Fractal and the transformers using:

$resource = new FractalCollection( $scheduleItems, new ScheduleItemTransformer );
return $this->fractal->createData( $resource )->toArray();

I get this:

{
    "data": [
        {
            "id": "0a2b583e-732c-42b4-ae18-a2ae915816b8",
            "bookings": {
                "data": []
            }
        },
        {
            "id": "0b2128c0-330e-4391-a8aa-dfa29cfd0d63",
            "bookings": {
                "data": []
            }
        },
    ]
}

So the nested Booking(s) are for some reason not parsed/included... What am I missing?

Oh, and here are the transformers (again, simplified for brevity):

class BookingTransformer extends Fractal\TransformerAbstract
{
    public function transform( Booking $booking )
    {
        $return [
            'id' => $booking['id']
        ];
    }
}


class ScheduleItemTransformer extends Fractal\TransformerAbstract
{

    protected $defaultIncludes = [
        'bookings'
    ];

    public function transform( ScheduleItem $scheduleItem )
    {
        return [
            'id' => $item->id
        ];
    }

    public function includeBookings( ScheduleItem $scheduleItem )
    {
        return $this->collection( $scheduleItem->bookings(), new BookingTransformer );
    }
}

Phew, thanks for reading this far. If you also have any ideas to share, even better!

0 likes
5 replies
santiagogg's avatar

Try parseIncludes...

$resource = new FractalCollection( $scheduleItems, new ScheduleItemTransformer );
return $this->fractal->createData( $resource )->parseIncludes('bookings')->toArray();
craigsssmith's avatar
Level 1

I think it's because you're calling the bookings() function, instead of referencing the dynamically generated bookings property, like so:

public function includeBookings( ScheduleItem $scheduleItem )
{
    return $this->collection( $scheduleItem->bookings, new BookingTransformer() );
}
3 likes
Davva's avatar
Level 10

Yes that was the problem. Thanks!

pezhman's avatar

How can we get the bookings data within the JSON?

Can I do:


public function includeBookings( ScheduleItem $scheduleItem )
{
    return $this->collection( $scheduleItem->bookings->find($scheduleItem->id), new BookingTransformer() );
}

kahovn's avatar

Hello, how can filter data in Booking model?

Please or to participate in this conversation.