58

So I can do this with Eloquent:

$roles = DB::table('roles')->lists('title', 'name');

But is there a way to make Eloquent fetch an array of values for each distinct key instead of just one column?

For instance, something like the following:

$roles = DB::table('roles')->lists(['*', DB:raw('COALESCE(value, default_value)')], 'name');
eComEvo
  • 11,669
  • 26
  • 89
  • 145

3 Answers3

115

You can use the keyBy method:

$roles = Role::all()->keyBy('name');

If you're not using Eloquent, you can create a collection on your own:

$roles = collect(DB::table('roles')->get())->keyBy('name');

If you're using Laravel 5.3+, the query builder now actually returns a collection, so there's no need to manually wrap it in a collection again:

$roles = DB::table('roles')->get()->keyBy('name');
Joseph Silber
  • 214,931
  • 59
  • 362
  • 292
  • I haven't had a chance to test out 4.2 yet but it will be in my next project. This looks like a very simple solution and I'm glad to see this was implemented. – eComEvo Jun 30 '14 at 11:56
  • 10
    @eComEvo - [I personally implemented it](https://github.com/laravel/framework/pull/4828) just for you :) – Joseph Silber Jul 01 '14 at 14:13
  • Note: This still uses foreach loop inside, so for performance it won't make a big difference, it'll only be more Laravel way. – Arda Dec 04 '14 at 12:11
  • In Laravel 5.1 in second case it doesn't work, laravel says all() method is not defined. I used get() instead – Victor Dec 01 '15 at 12:12
  • 1
    In 5.4, if you're using keyBy with toArray(), you need to call get(), keyBy() and then toArray(). Worked like a charm! – cbloss793 Apr 12 '17 at 22:39
32

If you need a key/value array, since Laravel 5.1 you can use pluck. This way you can indicate which attributes you want to use as a value and as a key.

$plucked = MyModel::all()->pluck(
  'MyNameAttribute', 
  'MyIDAttribute'
);

return $plucked->all();

You will get an array as follow:

array:3 [▼
   1 => "My MyNameAttribute value"
   2 => "Lalalala"
   3 => "Oh!"
]
tomloprod
  • 7,472
  • 6
  • 48
  • 66
  • 1
    why `pluck(id,name)` gives `[name=> id]` instead of `[id=>name]`? – San Apr 24 '20 at 14:34
  • @San Its a good answer (I asked myself the same) This is becase the first parameter of `pluck` is for assign the array value, so, when you use the second parameter, the second parameter specify the ID of the array. See this: https://laravel.com/api/5.5/Illuminate/Database/Eloquent/Collection.html#method_pluck – tomloprod Apr 24 '20 at 15:02
  • @tomloprod Your given solution in laravel 8.x but I want to concat 2 columns/fields values and want to use in selectbox. I have tried `$plucked = VehicleBrand::all()->pluck( DB::raw('concat(vb_brand_name," (",vb_brand_code,")") as vb_brand_name'), 'vb_id', );` but this is not working. any suggestion? Thanks. – Kamlesh Dec 27 '21 at 13:25
10

You may try something like this:

$roles = array();
array_map(function($item) use (&$roles) {
    $roles[$item->id] = (Array)$item; // object to array
}, DB::table('roles')->get());

If you want to get an Object instead of an Array as value then just remove the (Array).

Alternative: Using Eloquent model (Instead of DB::table):

$roles = array();
array_map(function($item) use (&$roles) {
    $roles[$item['id']] = $item;
}, Role::all()->toArray());

Another Alternative: Using Collection::map() method:

$roles = array();
Role::all()->map(function($item) use(&$roles) {
    $roles[$item->id] = $item->toArray();
});
The Alpha
  • 143,660
  • 29
  • 287
  • 307
  • 1
    Was hoping there was a built-in method I was just missing in the docs but this will do. Cleaner than the foreach loop I was originally using. :) – eComEvo Jun 10 '14 at 01:19