0

I am writing because I have spent hours of testing looking for a solution to a problem and I still have not found how to solve it. I am using Spatie Laravel Permission and it happens that I have 3 resources, one for user, another for role and another for permissions. I show the structure of the mentioned resources:

UserResource.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', $this->getAllPermissions())),
            'active' => $this->active,
        ];
    }
}

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'))
        ];
    }
}

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 my UserResource.php file, I am defining a structure to display user roles and permissions only when required. You can also see that in the permissions key, I am not returning only the permissions associated with the user, I am returning all the permissions directly associated with the user and associated with the roles they have getAllPermissions().

Now look at the RoleResource.php file, I am defining that the permissions associated with the role will be displayed only when necessary, and here is my problem. When I do the following:

public function index()
{
    return UserResource::make(User::with(['roles', 'permissions'])->find(1));
}

I am getting the following response:

imagen

Look at the key: roles, It is showing me the permissions relation, and that is not the expected result, I expect it to show me that result only when I do the following:

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

I've been doing a lot of testing and everything seems to indicate that when I call the method getAllPermissions() also load the permissions relation and that is why this is happening. Please could you help me with this problem. Thank you very much in advance.

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

1 Answers1

0

I was having the exact same problem. The only difference is that I only wanted to load 1 role since my users will only ever have one role. How I got around it was:

In UserResource.php

$user = [
    'id' => $this->id,
    'name' => $this->name,
    'email' => $this->email,
    'role' => $this->roles[0]->name,
];

if ($this->relationLoaded('permissions')) {
    $user['permissions'] = PermissionResource::collection($this->getAllPermissions());
}

return $user;

And then in UserController.php:

new UserResource(User::load('permissions')->get());

I don't know if this is correct but it's the only way I currently found to get around this issue. This works for me because I always want to only see the role name of my user. I guess for your problem you could use the same check in your RoleResource.php $this->relationLoaded('roles.permissions')