Trying to remove data in Fractal by implementing ArraySerializer in Laravel 5.2
Asked Answered
C

2

8

I've got the API working using the standard process, but I want to remove the data namespace from the JSON output. I see I need to implement ArraySerializer, I have been through the Fractal docs, but I can't work out where I need to added it in Laravel 5.2

I found this answer but I'm just getting the same output at the line of code I commented out:

class TrackController extends ApiController
{
    public function index()
    {
        $tracks = Track::all();
        //return $this->respondWithCollection($tracks, new TrackTransformer);
        // Same response as the commented out line above
        $response = new \League\Fractal\Resource\Collection($tracks, new TrackTransformer);
        $manager = new \League\Fractal\Manager();
        $manager->setSerializer(new \League\Fractal\Serializer\ArraySerializer());
        return response()->json($manager->createData($response)->toArray());
    }

    public function show($id)
    {
        $track = Track::find($id);
        return $this->respondWithItem($track, new TrackTransformer);
    }
}

Also, I'm implementing this on a specific controller, even if I got this working, where do I add the code/class so I can get ArraySerializer output for all my controllers?

I've posted this on Github if that helps.

Cesta answered 28/3, 2016 at 13:19 Comment(16)
first impression, i think you should move $response = new \League\Fractal\Resource\Collection($tracks, new TrackTransformer); after you set serializerMacaluso
Where would I move it to?Cesta
$manager = new \League\Fractal\Manager(); $manager->setSerializer(new \League\Fractal\Serializer\ArraySerializer()); $response = new \League\Fractal\Resource\Collection($tracks, new TrackTransformer); Macaluso
Thanks for the response. however, I'm still getting the same result with data.Cesta
when you have use ArraySerializer u can set you key this way $response = new \League\Fractal\Resource\Collection($tracks, new TrackTransformer, 'MYKEY') without specify a key, fractal will automatically fall back to use the data keyMacaluso
Thanks, thats worked - Now I need to make it work for included items :)Cesta
for your information, there is a package call Cyvelnet/laravel5-fractal may save you some times in making data tranformationMacaluso
Thanks, looks good - Im going try it now.Cesta
@terrylow It doesn't work for me, gives error { "message": "The Response content must be a string or object implementing __toString(), \"object\" given.", "status_code": 500 } and this is my code return new \League\Fractal\Resource\Collection($request->user->friends, new FriendTransformer(), 'friends');Cuffs
@RohitKhatri i belive you have forgotten to cast it to array or to json $manager->createData($response)->toArray()Macaluso
@terrylow can you please give me a working example?Cuffs
@terrylow ok somehow I got it working, but still getting the data key instead friends, here's my new code $resource = (new \League\Fractal\Resource\Collection($request->user->friends, new FriendTransformer(), 'friends')); $manager = new Manager(); return $manager->createData($resource)->toArray(); can you tell me what I'm doing wrong?Cuffs
@RohitKhatri please add this line $manager->setSerializer(new \League\Fractal\Serializer\ArraySerializer()); before you instantial fractal manager, because fractal uses DataArraySerializer which will uses data namespaceMacaluso
It's working now, and can you tell me how should I implement it so I don't have to write these lines again and again instead $this->response->collection($collection, new Transformer, 'key') ? ThanksCuffs
if you prefer not to use 3rd party packages, then add a new method response() to your base Controller class, then instantial your fractal manager in response method and return a initialized managerMacaluso
@terrylow Thank you so much, you saved my time.Cuffs
A
6

You need create own MySerializer extends of DataArraySerializer and use it instead of default. Default DataArraySerializer have three methods and in each of them need change return values to this:

use League\Fractal\Serializer\DataArraySerializer;

class MySerializer extends DataArraySerializer
{
    /**
     * Serialize a collection.
     *
     * @param string $resourceKey
     * @param array  $data
     *
     * @return array
     */
    public function collection($resourceKey, array $data)
    {
        return $data;
    }

    /**
     * Serialize an item.
     *
     * @param string $resourceKey
     * @param array  $data
     *
     * @return array
     */
    public function item($resourceKey, array $data)
    {
        return $data;
    }

    /**
     * Serialize null resource.
     *
     * @return array
     */
    public function null()
    {
        return [];
    }

}

So you change the behavior of the serialize mechanism and get result as you wish.

Atelectasis answered 11/4, 2017 at 13:33 Comment(1)
Thanks! Too bad this isn't a built-in option.Pryce
C
4

If you use spatie/laravel-fractal package or spatie/fractalistic, then you can remove the data key from the results by using the Spatie array serializer Spatie\Fractalistic\ArraySerializer() instead of the Fractal's default serializer.

You can use is like this:

Fractal::create()
   ->collection($books)
   ->transformWith(function($book) { return ['id' => $book['id']];})
   ->serializeWith(new \Spatie\Fractalistic\ArraySerializer())
   ->toArray();

This will return..

[
    ['id' => 1],
    ['id' => 2]
]

Instead of..

[
    'data' => [
        ['id' => 1],
        ['id' => 2]
    ]
]

Or, if you want to use the Spatie serializer globally, add it in the config/fractal.php file like this:

<?php

return [
    /*
     * The default serializer to be used when performing a transformation. It
     * may be left empty to use Fractal's default one. This can either be a
     * string or a League\Fractal\Serializer\SerializerAbstract subclass.
     */
    'default_serializer' => new Spatie\Fractalistic\ArraySerializer(),
    .
    .
    .
];

More info, see: Using a serializer

Clodhopper answered 8/3, 2018 at 13:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.