Pluck with multiple columns?

2020-03-12 03:34发布

When i use pluck with multiple columns i get this:

{"Kreis 1 \/ Altstadt":"City","Kreis 2":"Enge","Kreis 3":"Sihifeld","Kreis 4":"Hard","Kreis 5 \/ Industriequartier":"Escher Wyss","Kreis 6":"Oberstrass","Kreis 7":"Witikon","Kreis 8 \/ Reisbach":"Weinegg","Kreis 9":"Altstetten","Kreis 10":"Wipkingen","Kreis 11":"Seebach","Kreis 12 \/ Schwamendingen":"Hirzenbach"

But i need this?

["Rathaus","Hochschulen","Lindenhof","City","Wollishofen","Leimbach","Enge","Alt-Wiedikon","Friesenberg","Sihifeld","Werd","Langstrasse","Hard","Gewerbechule","Escher Wyss","Unterstrass","Oberstrass","Fluntern","Hottingen","Hirslanden","Witikon","Seefeld","M\u00fchlebach","Weinegg","Albisrieden","Altstetten","H\u00f6ngg","Wipkingen","Affoltern","Oerlikon","Seebach","Saatlen","Schwamendingen-Mitte","Hirzenbach"]

Any suggestion how can i do that? This is my method:

    public function autocomplete_districts(Request $request)
   {
      $district = $request->input('query');
      // $ass = /DB::table('districts')->select(array('district', 'region'))->get();
      // dd($ass);
      $data = Districts::whereRaw('LOWER(district) like ?', [strtolower('%'.$district . '%')])->orWhereRaw('LOWER(region) like ?', [strtolower('%'.$district . '%')])->pluck('region','district');

      return response()->json($data);
   }

6条回答
Luminary・发光体
2楼-- · 2020-03-12 04:11

I have created the model scope

More about scopes:

Code:

/**
 * Scope a query to Pluck The Multiple Columns
 *
 * This is Used to Pluck the multiple Columns in the table based
 * on the existing query builder instance
 *
 * @author Manojkiran.A <manojkiran10031998@gmail.com>
 * @version 0.0.2
 * @param  \Illuminate\Database\Eloquent\Builder $query
 * @param string $keyColumn the columns Which is used to set the key of array
 * @param array $extraFields the list of columns that need to plucked in the table
 * @return \Illuminate\Support\Collection
 * @throws Illuminate\Database\QueryException
 **/
public function scopePluckMultiple( $query, string $keyColumn, array $extraFields):\Illuminate\Support\Collection
{
    //pluck all the id based on the query builder instance class
    $keyColumnPluck = $query->pluck( $keyColumn)->toArray();
    //anonymous callback method to iterate over the each fileds of table
    $callBcakMethod = function ($eachValue) use ($query)
    {
        $eachQuery[$eachValue] = $query->pluck( $eachValue)->toArray();
        return $eachQuery;
    };
    //now we are collapsing the array single time to get the propered array 
    $extraFields = \Illuminate\Support\Arr::collapse( array_map($callBcakMethod, $extraFields));

    // //iterating Through All Other Fields and Plucking it each Time
    // foreach ((array)$extraFields as  $eachField) {
    //         $extraFields[$eachField] =   $query->pluck($eachField)->toArray();
    //     }

    //now we are done with plucking the Required Columns
    //we need to map all the values to each key

    //get all the keys of extra fields and sets as array key or index
    $arrayKeys = array_keys($extraFields);
    //get all the extra fields array and mapping it to each key
    $arrayValues = array_map(
        function ($value) use ($arrayKeys) {
            return array_combine($arrayKeys, $value);
        },
        call_user_func_array('array_map', array_merge(
            array(function () {
                return func_get_args();
            }),
            $extraFields
        ))
    );
    //now we are done with the array now Convert it to Collection
    return collect( array_combine( $keyColumnPluck, $arrayValues));
}

So now the testing part

BASIC EXAMPLE

$basicPluck  = Model::pluckMultiple('primaryKeyFiles',['fieldOne', 'FieldTwo']);

ADVANCED EXAMPLE

$advancedPlcuk  = Model::whereBetween('column',[10,43])
                            ->orWhere('columnName','LIKE', '%whildCard%')
                            ->Where( 'columnName', 'NOT LIKE', '%whildCard%')
                            ->pluckMultiple('primaryKeyFiles',['fieldOne', 'FieldTwo']);

But it returns the \Illuminate\Support\Collection, so if you need to convert to array

$toArrayColl = $advancedPluck->toArray();

if you need to convert to json

$toJsonColl = $advancedPluck->toJson();
查看更多
Juvenile、少年°
3楼-- · 2020-03-12 04:12

My solution in LARAVEL 5.6:

Hi, I've just had the same problem, where I needed 2 columns combined in 1 select list. My DB has 2 columns for Users: first_name and last_name. I need a select box, with the users full name visible and the id as value. This is how I fixed it, using the pluck() method:

In the User model I created a full name accessor function:

public function getNameAttribute() {
    return ucwords($this->last_name . ' ' . $this->first_name);
}

After that, to fill the select list with the full name & corresponding database id as value, I used this code in my controller that returns the view (without showing users that are archived, but you can change the begin of the query if you like, most important are get() and pluck() functions:

$users = User::whereNull('archived_at')
    ->orderBy('last_name')
    ->get(['id','first_name','last_name'])
    ->pluck('name','id');
return view('your.view', compact('users'));

Now you can use the $users in your select list!

So first, you GET all the values from DB that you will need, after that you can use any accessor attribute defined for use in your PLUCK method,

as long as all columns needed for the accessor are in the GET ;-)

查看更多
劳资没心,怎么记你
4楼-- · 2020-03-12 04:15

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.

查看更多
小情绪 Triste *
5楼-- · 2020-03-12 04:17

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

/**
 * 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.
            array_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' => 'john@email.com'],
//     ['name' => 'Jane Doe', 'username' => 'jane', 'email' => 'jane@email.com'],
//     ['name' => 'Joe Bloggs', 'username' => 'joe', 'email' => 'joe@email.com'],
// ]

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' => 'john@email.com', 'posts' => [...]],
//     ['fullname' => 'Jane Doe', 'email' => 'jane@email.com', 'posts' => [...]],
//     ['fullname' => 'Joe Bloggs', 'email' => 'joe@email.com', 'posts' => [...]],
// ]
查看更多
唯我独甜
6楼-- · 2020-03-12 04:18

Laravel: To pluck multi-columns in the separate arrays use the following code.

$Ads=Ads::where('status',1);
$Ads=$Ads->where('created_at','>',Carbon::now()->subDays(30));
$activeAdsIds=$Ads->pluck('id'); // array of ads ids
$UserId=$Ads->pluck('user_id'); // array of users ids
查看更多
叛逆
7楼-- · 2020-03-12 04:28

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();
查看更多
登录 后发表回答