0

I have a problem when returning an api resource. I am using Spatie Laravel Permission.

It happens that in my particular case I am trying to return an api resource with the details of the user and next to them the roles and permissions that the user has.

My UserResorce.php

class UserResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param Request $request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'email' => $this->email,
            'roles' => RoleResource::collection($this->whenLoaded('roles')),
            'permissions' => PermissionResource::collection($this->whenLoaded('permissions')),
        ];
    }
}

My RoleResource.php

class RoleResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param Request $request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'permissions' => PermissionResource::collection($this->whenLoaded('permissions'))
        ];
    }
}

My PermissionResource.php

class PermissionResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param Request $request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name
        ];
    }
}

As you can see in the UserResource.php file, I only load the roles and permissions when they are really needed. In this way if I do the following:

class UserController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return Response
     */
    public function index()
    {
        return UserResource::make(User::find(1));
    }

I get the following result:

{
  "data": {
    "id":1,
    "name":"User Name 1",
    "email":"admin@example.com",
  }
}

So to load the same result but this time with the roles associated with the user I do the following:

class UserController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return Response
     */
    public function index()
    {
        return UserResource::make(User::with(['roles'])->find(1));
    }

and as expected I get the following result:

{
  "data": {
    "id":1,
    "name":"User Name 1",
    "email":"admin@example.com",
    "roles": {
      0: {
        "id": 1,
        "name": "Administrator",
      }
    }
  }
}

Now my problem is the following, to get the user roles and permissions I did the following:

class UserController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return Response
     */
    public function index()
    {
        return UserResource::make(User::with(['roles', 'permissions'])->find(1));
    }

but I get an empty object in the "permissions" key, so I analyzed more carefully and it is that the permissions that user has are defined by their role, I looked in the documentation and I saw that I can obtain all the permissions of a user using getAllPermissions() method. So I did the following:

class UserResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param Request $request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'email' => $this->email,
            'roles' => RoleResource::collection($this->whenLoaded('roles')),
            'permissions' => PermissionResource::collection($this->whenLoaded('permissions', function () {
                return $this->getAllPermissions();
            })),
        ];
    }
}

but in this way, it also loads the permissions in the roles relation and it would obtain an unexpected result like the following:

{
  "data": {
    "id":1,
    "name":"User Name 1",
    "email":"admin@example.com",
    "roles": {
      0: {
        "id": 1,
        "name": "Administrator",
        "permissions": {
          0: {
            "id": 1
            "name": "Create Users"
          }
        }
      }
    },
    "permissions": {
      0: {
        "id": 1,
        "name": "Create Users",
     }
  }
}

and it is not the expected result, since the result that I expect when executing:

return UserResource::make(User::with(['roles', 'permissions'])->find(1));

should by the following:

{
  "data": {
    "id":1,
    "name":"User Name 1",
    "email":"admin@example.com",
    "roles": {
      0: {
        "id": 1,
        "name": "Administrator",
      }
    },
   "permissions": {
      0: {
        "id": 1,
        "name": "Create Users",
     }
  }
}

and when execute:

return UserResource::make(User::with(['roles.permissions', 'permissions'])->find(1));

I expect the following result:

{
  "data": {
    "id":1,
    "name":"User Name 1",
    "email":"admin@example.com",
    "roles": {
      0: {
        "id": 1,
        "name": "Administrator",
        "permissions": {
          0: {
            "id": 1
            "name": "Create Users"
          }
        }
      }
    },
    "permissions": {
      0: {
        "id": 1,
        "name": "Create Users",
     }
  }
}

Could someone help me with this problem? Thank you very much in advance.

apokryfos
  • 38,771
  • 9
  • 70
  • 114
leo95batista
  • 699
  • 9
  • 27

0 Answers0