12

is it there an easy way to remove the "data" envelope from the Dingo API response.

When I use this Transformer to transform user models:

class UserTransformer extends EloquentModelTransformer
{

    /**
     * List of resources possible to include
     *
     * @var array
     */
    protected $availableIncludes = [
        'roles'
    ];

    protected $defaultIncludes = [
        'roles'
    ];

    public function transform($model)
    {
        if(! $model instanceof User)
            throw new InvalidArgumentException($model);

        return [
            'id' => $model->id,
            'name' => $model->name,
            'email' => $model->email
        ];
    }

    /**
     * Include Roles
     *
     * @param User $user
     * @return \League\Fractal\Resource\Item
     */
    public function includeRoles(User $user)
    {
        $roles = $user->roles;

        return $this->collection($roles, new RoleTransformer());
    }

I get this response:

{
data : [
      "id": 102,
      "name": "Simo",
      "email": "mail@outlook.com",
      "roles": {
        "data": [
          {
            "id": 1    
            "name": "admin"
          }
        ]
      }
    }
]
}

I read some articles about RESTful APIs and a lot of them stated that such enveloped responses arent very modern (You should use the HTTP Header instead).

How can I disable this behaviour at least for the includes?

Thank you

Simon Schneider
  • 1,216
  • 1
  • 15
  • 23
  • 1
    I am not sure but you could use this https://github.com/dingo/api/wiki/Responses#morphing-and-morphed-events and morph your response before sending but yes, definitely is not an easy way. – Bharat Geleda Oct 31 '15 at 18:45
  • Go to [repository](https://github.com/dingo/api/issues?q=is%3Aissue+remove+data+is%3Aclosed), search for what you are asking in ticket section ("remove data") etc.. make your own ticket.. That's what you do when something is on github. btw: +1 from me; just my 2 pennies. – Kyslik Nov 25 '15 at 15:49

3 Answers3

14

For those who fall on this later and as I had really hard time to make it, I'd like to share how I made it working in my API :

1) Create a Custom Serializer, NoDataArraySerializer.php :

namespace App\Api\V1\Serializers;

use League\Fractal\Serializer\ArraySerializer;

class NoDataArraySerializer extends ArraySerializer
{
    /**
     * Serialize a collection.
     */
    public function collection($resourceKey, array $data)
    {
        return ($resourceKey) ? [ $resourceKey => $data ] : $data;
    }

    /**
     * Serialize an item.
     */
    public function item($resourceKey, array $data)
    {
        return ($resourceKey) ? [ $resourceKey => $data ] : $data;
    }
}

2) Set new the Serializer. In bootstrap/app.php, add :

$app['Dingo\Api\Transformer\Factory']->setAdapter(function ($app) {
    $fractal = new League\Fractal\Manager;
    $fractal->setSerializer(new App\Api\V1\Serializers\NoDataArraySerializer);
    return new Dingo\Api\Transformer\Adapter\Fractal($fractal);
});

That's it.

Now, in your UserController (for instance), you can use it like this :

namespace App\Api\V1\Controllers;

use App\Api\V1\Models\User;
use App\Api\V1\Transformers\UserTransformer;

class UserController extends Controller
{
    public function index()
    {
        $items = User::all();

        return $this->response->collection($items, new UserTransformer());
    }
}

And the response will look like :

[
    {
        "user_id": 1,
        ...
    },
    {
        "user_id": 2,
        ...
    }
]

Or, I you want to add an enveloppe, you just need to set the resource key in the Controller. Replace :

return $this->response->collection($items, new UserTransformer());

by

return $this->response->collection($items, new UserTransformer(), ['key' => 'users']);

And the response will look like :

{
    "users": [
        {
            "user_id": 1,
            ...
        },
        {
            "user_id": 2,
            ...
        }
    ]
}
YouHieng
  • 156
  • 1
  • 4
4

One addition to the solution of YouHieng. The preferred way to register the NoDataArraySerializer in Laravel 5.3 and above is to write a custom ServiceProvider and add the logic into the boot() method and not the bootstrap/app.php file.

For Example:

php artisan make:provider DingoSerializerProvider

Then:

public function boot(){
    $this->app['Dingo\Api\Transformer\Factory']->setAdapter(function ($app) {
        $fractal = new League\Fractal\Manager;
        $fractal->setSerializer(new App\Http\Serializers\NoDataArraySerializer());
        return new Dingo\Api\Transformer\Adapter\Fractal($fractal);
    });
}
SilverNak
  • 3,283
  • 4
  • 28
  • 44
3

Have a look to http://fractal.thephpleague.com/serializers/#arrayserializer. They explain exactly what to do when

Sometimes people want to remove that 'data' namespace for items

guest
  • 31
  • 2