32

I have a model Role which belongs to many Users.

Class Role {
     public $fillable = ["name"];

     public function users()
     {
          return $this->belongsToMany('App/Models/User')->select(['user_id']);
     }
}

When I retrieve users using with query in Role. I want It would return only user_ids array

 Role::with("users")->get();

it should return the following output

 [ 
   {
     "name": "Role1",
     "users" : [1,2,3]
   },
   {
     "name": "Role2",
     "users" : [1,2,3]
   }
 ]

Currently it gives following output

[ 
   {
     "name": "Role1",
     "users" : [
        {
           user_id : 1
        },
        {
           user_id : 2
        },

        {
           user_id : 3
        }
   },
   {
     "name": "Role2",
     "users" : [
        {
           user_id : 1
        },
        {
           user_id : 2
        },

        {
           user_id : 3
        }
     ]
   }
 ]
sp11
  • 323
  • 1
  • 3
  • 6

1 Answers1

51

Personally, I wouldn't change the users() relationship, but maybe add an accessor for user IDs

class Role {
    protected $fillable = ["name"];

    // adding the appends value will call the accessor in the JSON response
    protected $appends = ['user_ids'];

    public function users()
    {
         return $this->belongsToMany('App/Models/User');
    }

    public function getUserIdsAttribute()
    {
        return $this->users->pluck('user_id');
    }
}

Then you still have a working relationship, but can access the user IDs as an array in the Role response. If that doesn't work for you, as mentioned by @Creator, you could probably just add ->pluck('id') in the relationship rather than the select()

benJ
  • 2,442
  • 1
  • 18
  • 16
  • 4
    In Laravel 5.5+ I needed to do `return $this->users->pluck('pivot.user_id');` or just to use the "id". – llioor Jan 15 '18 at 16:03
  • 3
    THIS IS SLOW - you are accessing this using `$this->users->pluck()` should be `$this->users()->pluck('feild')->get()` – AndrewMcLagan Jul 05 '18 at 07:06
  • 3
    @AndrewMcLagan erm, nope, calling `$this->users()` returns the query builder. Calling `$this->users` returns the eager-loaded collection. You could do `$this->users()->pluck('field')`, but that would be slower as you're repeating the query. – benJ Jul 05 '18 at 08:51
  • 2
    [here](https://laracasts.com/discuss/channels/general-discussion/eloquent-get-relations-id-belongstomany) the guys used `$this->users()->allRelatedIds();`. Does your tip apply here too, @benJ? – giovannipds Jan 10 '19 at 18:41
  • Tested both and they make different queries for me: 1) `pluck` seems to make this long query: `select agents.*, agent_price_table.price_table_id as pivot_price_table_id, agent_price_table.agent_id as pivot_agent_id from agents inner join agent_price_table on agents.id = agent_price_table.agent_id where agent_price_table.price_table_id = 20`; 2) while `allRelatedIds` makes a very shorten one: `select agent_id from agent_price_table where price_table_id = 20`. But apparently both make an additional query. – giovannipds Jan 10 '19 at 18:43
  • @benJ I tried it here and apparently either way will going to make a query for each row. – giovannipds Jan 10 '19 at 18:53
  • just a comment. Then you will cal it as `$aRole->getUserIdsAttribute()` not `$aRole->getUserIdsAttribute` – CodeToLife Dec 13 '20 at 11:15