Fractal transformer with different Serializers for nested items and collections

Viewed 2362

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  
    }
}
2 Answers

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.

Related