Pluck with multiple columns?

Cos that is how pluck works. Instead try this.

$data = Districts::whereRaw('LOWER(district) like ?', [strtolower('%'.$district . '%')])->orWhereRaw('LOWER(region) like ?', [strtolower('%'.$district . '%')])->select('region', 'district')->get();

$data = collect($data->toArray())->flatten()->all();

You should use select() with get() and then later on modify the object as you need.

So instead of: ->pluck('region','district'); use: ->select('region','district')->get();

pluck() is advised when you need value of one column only.

And as far as possible, you should have your models singular form not plural (Districts) - to follow Laravel nomenclature.


In my case I wanted to pluck 2 values from an array of Eloquent models and this worked:

$models->map->only(['state', 'note'])->values()

That's shorter version of

$models->map(fn($model) => $model->only(['state', 'note']))->values()

This is an issue I constantly have faced and has led me to create the following solution that can be used on models or arrays.
There is also support for dot syntax that will create a multidimensional array as required.

Register this macro within the AppServiceProvider (or any provider of your choice):

use Illuminate\Support\Arr;

/**
* Similar to pluck, with the exception that it can 'pluck' more than one column.
* This method can be used on either Eloquent models or arrays.
* @param string|array $cols Set the columns to be selected.
* @return Collection A new collection consisting of only the specified columns.
*/
Collection::macro('pick', function ($cols = ['*']) {
    $cols = is_array($cols) ? $cols : func_get_args();
    $obj = clone $this;

    // Just return the entire collection if the asterisk is found.
    if (in_array('*', $cols)) {
        return $this;
    }

    return $obj->transform(function ($value) use ($cols) {
        $ret = [];
        foreach ($cols as $col) {
            // This will enable us to treat the column as a if it is a
            // database query in order to rename our column.
            $name = $col;
            if (preg_match('/(.*) as (.*)/i', $col, $matches)) {
                $col = $matches[1];
                $name = $matches[2];
            }

            // If we use the asterisk then it will assign that as a key,
            // but that is almost certainly **not** what the user
            // intends to do.
            $name = str_replace('.*.', '.', $name);

            // We do it this way so that we can utilise the dot notation
            // to set and get the data.
            Arr::set($ret, $name, data_get($value, $col));
        }

        return $ret;
    });
});

This can then be used in the following way:

$a = collect([
    ['first' => 1, 'second' => 2, 'third' => 3],
    ['first' => 1, 'second' => 2, 'third' => 3]
]);

$b = $a->pick('first', 'third'); // returns [['first' => 1, 'third' => 3], ['first' => 1, 'third' => 3]]

Or additionally, on any models you may have:

$users = User::all();
$new = $users->pick('name', 'username', 'email');
// Might return something like:
// [
//     ['name' => 'John Doe', 'username' => 'john', 'email' => '[email protected]'],
//     ['name' => 'Jane Doe', 'username' => 'jane', 'email' => '[email protected]'],
//     ['name' => 'Joe Bloggs', 'username' => 'joe', 'email' => '[email protected]'],
// ]

It is also possible to reference any relationship too using the dot notation, as well as using the as [other name] syntax:

$users = User::all();
$new = $users->pick('name as fullname', 'email', 'posts.comments');
// Might return something like:
// [
//     ['fullname' => 'John Doe', 'email' => '[email protected]', 'posts' => [...]],
//     ['fullname' => 'Jane Doe', 'email' => '[email protected]', 'posts' => [...]],
//     ['fullname' => 'Joe Bloggs', 'email' => '[email protected]', 'posts' => [...]],
// ]