4

I'm trying to get the authenticated user object from the request with roles. I'm using Spatie laravel-permissions and Laravel 8.

Getting User object from request like so

$request->user()->getRoleNames()->pluck('name');
return $request->user();

Returns

{
   "id":1,
   "name":"User name",
   "email":"User email",
   "email_verified_at":null,
   "company":"--",
   "phone":"--",
   "created_at":"--",
   "updated_at":"--",
   "roles":[
      {
         "id":1,
         "name":"Super Admin",
         "guard_name":"web",
         "created_at":"--",
         "updated_at":"--",
         "pivot":{
            "model_id":1,
            "role_id":1,
            "model_type":"App\\Models\\User"
         }
      }
   ]
}

What I need to be returned

{
   "id":1,
   "name":"User name",
   "email":"User email",
   "email_verified_at":null,
   "company":"--",
   "phone":"--",
   "created_at":"--",
   "updated_at":"--",
   "roles":["Super Admin"]
}
Josh Bonnick
  • 2,281
  • 1
  • 10
  • 21

3 Answers3

2

Added roles to user object, like so

$user = $request->user();
$user->roles = $user->roles()->pluck('name');
return $user;
Josh Bonnick
  • 2,281
  • 1
  • 10
  • 21
  • 1
    I should mention this approach is perfectly fine, but if you have more than one place you need to do this, it can get painful to maintain that :) – Tim Lewis Oct 27 '20 at 20:20
2

Another alternative is using hidden, appends and an accessor, like getRoleNamesAttribute():

class User extends Model {
  ...

  // This will hide `roles` from your `User`, when converted to JSON/Array/etc
  protected $hidden = ['roles'];

  // This will add `role_names` to your `User`, when converted to JSON/Array/etc
  protected $appends = ['role_names'];

  // Accessible via `$user->role_names`, or `user.role_names` in JSON
  public function getRoleNamesAttribute() {
    return $this->roles->pluck('name'); 
  }

  ... // Everything else
}

Doing this, in conjunction with return $request->user(); will automatically make roles invisible, and appends role_names. In your code, you should get the output:

{
   "id":1,
   "name":"User name",
   "email":"User email",
   "email_verified_at":null,
   "company":"--",
   "phone":"--",
   "created_at":"--",
   "updated_at":"--",
   "role_names":["Super Admin"]
}
Tim Lewis
  • 27,813
  • 13
  • 73
  • 102
  • 1
    This method looks great for the long run, I did try with attributes but I think I needed to add roles to hidden for it work which I didn't do the first time. Thanks for your response, I'll be using this rather than mine. I'll accept it as the answer to make that clear for others. – Josh Bonnick Oct 27 '20 at 20:35
  • 1
    It's definitely easier to maintain in the long run; only having to modify a single spot vs many calls is much nicer. It can get a little confusing if you have nested models/relationships, each with their own hidden/visible/appends/etc, but once you understand how it all works, it's pretty great :) – Tim Lewis Oct 27 '20 at 20:38
0

You can also do this:

$user->roles = User::find($user->id)->getRoleNames();
Sylar
  • 187
  • 13