dingo / api

A RESTful API package for the Laravel and Lumen frameworks.
BSD 3-Clause "New" or "Revised" License
9.33k stars 1.25k forks source link

Change resourceKey when using withPaginator #1254

Open makz27 opened 7 years ago

makz27 commented 7 years ago

Hello

I'm new to api but as i saw, when i list all my users in a normal way i have a response like that

"users" : [ ... ]

Okay for that, ember.js models like this everything is ok because my resourcekey is the same as my model.

I wanna use the pagination, so i use

$users = User::paginate(50);

return $this->response->withPaginator($users, new UserTransformer);

My transformer look like

use App\User;
use League\Fractal;

class UserTransformer extends Fractal\TransformerAbstract
{
    public function transform(User $user)
    {
        return [
            'username'   => $user->username,
        ];
    }
}

But it return me the json with "data" resourcekey

{
  "data": [
    {
      "username": "superuser"
    },
    {
      "username": "administrator"
    }
  ],
  "meta": {
    "pagination": {
      "total": 2,
      "count": 2,
      "per_page": 50,
      "current_page": 1,
      "total_pages": 1,
      "links": []
    }
  }
}

Is it possible to change the resource key to "users" ? Should i change the resource key or api guidelines only recommend a "data" resourcekey ? I don't know if ember will like to have a "data" resource key for user listing when all other requests respond with "users" : [].

makz27 commented 7 years ago

Up ?

jasonlewis commented 7 years ago

What Fractal serializer? And are you setting your resource keys?

return $this->response->withPaginator($users, new UserTransformer, ['key' => 'users']);
makz27 commented 7 years ago

Default serializer

'transformer' => env('API_TRANSFORMER', Dingo\Api\Transformer\Adapter\Fractal::class),

And yep, i tried to set ['key' => 'users'] and also i found 'resourceKey' but didn't work at all i still have the "data" enveloppe

fractal 0.15.0 dingo/api v1.0.0-beta7

Cannonb4ll commented 7 years ago

I have the exact same problem, have you been able to solve this yet?

makz27 commented 7 years ago

Hello,

Yes i resolved my problem yesterday and forgot to post the solution here :)

I didn't modify the api.php configuration, transformer stay the same

'transformer' => env('API_TRANSFORMER', Dingo\Api\Transformer\Adapter\Fractal::class),

Firstly i create a new serializer

// app/Api/V1/Serializers/CustomJsonSerializer.php

<?php namespace App\Api\V1\Serializers;

use League\Fractal\Pagination\CursorInterface;
use League\Fractal\Pagination\PaginatorInterface;
use League\Fractal\Serializer\SerializerAbstract;

/**
 * Create a new Serializer in your project
 */
use League\Fractal\Serializer\ArraySerializer;

class CustomJsonSerializer extends ArraySerializer
{
    public function collection($resourceKey, array $data)
    {
        if ($resourceKey === false) {
            return $data;
        }
        return array($resourceKey ?: 'data' => $data);
    }

    public function item($resourceKey, array $data)
    {
        if ($resourceKey === false) {
            return $data;
        }
        return array($resourceKey ?: 'data' => $data);
    }
}

And i set my new custom serializer inside the AppServiceProviders

// app\Providers\AppServiceProviders.php

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Dingo\Api\Transformer\Adapter\Fractal;
use League\Fractal\Manager;
use App\Api\V1\Serializers\CustomJsonSerializer;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        $this->app['Dingo\Api\Transformer\Factory']->setAdapter(function ($app) {
             $fractal = new Manager();
             $fractal->setSerializer(new CustomJsonSerializer());
             return new Fractal($fractal);
        });
    }

    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

And now the "data" enveloppe is named following the "key" parameter

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

But i think this should be a "built-in" feature while the REST standard need to have the model name in the response instead of "data".

Cannonb4ll commented 7 years ago

Ah yes, that works! :)

KatWei commented 6 years ago

hello,I create a CustomJsonSerializer,but nothing happend.

<?php

namespace App\Serializers;

use League\Fractal\Serializer\ArraySerializer;

class CustomJsonSerializer extends ArraySerializer
{

    public function collection($resourceKey, array $data)
    {
        $resultData = [
            'message' => 'success',
            'status_code' => 200,
            'data' => $data
        ];
        if (!empty($resourceKey)) {
            $resultData['total'] = $resourceKey;
        }
        return $resultData;
    }

    public function item($resourceKey, array $data)
    {
        return [
            'message' => 'success',
            'status_code' => 200,
            'data' => $data
        ];
    }
}

My DingoSerializerProvider:

<?php

namespace App\Providers;

use App\Serializers\CustomJsonSerializer;
use Illuminate\Support\ServiceProvider;
use Dingo\Api\Transformer\Adapter\Fractal;
use League\Fractal\Manager;

class DingoSerializerProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        $this->app['Dingo\Api\Transformer\Factory']->setAdapter(function ($app) {

            $fractal = new Manager();
            $fractal->setSerializer(new CustomJsonSerializer());
            return new Fractal($fractal);
        });
    }

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

and config/app.php

App\Providers\DingoSerializerProvider::class,