ChatGPT解决这个技术问题 Extra ChatGPT

Eloquent column list by key with array as values?

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');
Instead of lists, have you checked select ?
Yes, but it doesn't produce key value pairs like list() does.

J
Joseph Silber

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

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 - I personally implemented it just for you :)
Note: This still uses foreach loop inside, so for performance it won't make a big difference, it'll only be more Laravel way.
In Laravel 5.1 in second case it doesn't work, laravel says all() method is not defined. I used get() instead
In 5.4, if you're using keyBy with toArray(), you need to call get(), keyBy() and then toArray(). Worked like a charm!
t
tomloprod

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!"
]

why pluck(id,name) gives [name=> id] instead of [id=>name]?
@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: laravel.com/api/5.5/Illuminate/Database/Eloquent/…
@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.
T
The Alpha

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();
});

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. :)