4

To change the JSON output send by a Laravel 5.4 RESTful API, I make use of the Fractal package by thephpleague. Because pagination will be added in the future, it is important that collections make use of the default DataArraySerializer and single items use the ArraySerializer. It is also needed that deeper nested objects are given the same structure. How can I achieve this (globally or not)?

class TreeTransformer extends TransformerAbstract {
    protected $defaultIncludes = [
        'type',
        'branches'
    ];

    public function transform(Tree $tree) {
         return [
            'id' => (int)$tree->id,
            'name' => (string)$tree->name
        ];
    }

    public function includeType(Tree $tree) {
        return $this->item($tree->type, new TypeTransformer()); // Should be ArraySerializer  
    }

    public function includeBranches(Tree $tree) {
        return $this->collection($tree->branches, new BranchTransformer()); // Should stay DataArraySerializer  
    }
}
John Slegers
  • 45,213
  • 22
  • 199
  • 169
Sam
  • 1,303
  • 3
  • 23
  • 41
  • Are you using the wrapper / package laravel-fractal or just Fractal itself? – louisfischer Jun 02 '17 at 15:01
  • I installed the laravel-fractal package (vendor/spatie/laravel-fractal) so I assumed I was using that but it seems that sublime automatically included packages of Fractal itself, for example: League\Fractal\TransformerAbstract. – Sam Jun 02 '17 at 15:12
  • It is entirely normal, since laravel-fractal is _just_ a wrapper for The PHP League's Fractal package. It extends some of its classes. – louisfischer Jun 02 '17 at 15:42

2 Answers2

2

Unfortunately, I think what you are trying to do is not possible yet. More information here: https://github.com/thephpleague/fractal/issues/315

You can still change the serializer for an entire output like this: https://github.com/spatie/fractalistic#using-a-serializer. But it is not what you want to achieve.

louisfischer
  • 1,968
  • 2
  • 20
  • 38
2

Actually you can. It may look quite more verbose, but the trick is just not using $defaultIncludes. Use the fractal helper instead.

class TreeTransformer extends TransformerAbstract {

    public function transform(Tree $tree) {
         return [
            'id' => (int)$tree->id,
            'name' => (string)$tree->name,
            'type' => $this->serializeType($tree)
            'branches' => $this->serializeBranches($tree)
        ];
    }

    private function serializeType(Tree $tree) {
        return fractal()
                ->serializeWith(new ArraySerializer())
                ->collection($tree->type)
                ->transformWith(TypeTransformer::class)
                ->toArray(); // ArraySerializer  
    }

    private function serializeBranches(Tree $tree) {
        return fractal()
                ->serializeWith(new DataArraySerializer())
                ->collection($tree->branches)
                ->transformWith(BranchesTransformer::class)
                ->toArray(); // DataArraySerializer  
    }
}

It's working for me with ArraySerializer. Didn't try DataArraySerializer.

mayid
  • 1,644
  • 15
  • 23