【Laravel】pluckを使いこなせ!!!

今回はpluckメソッドってどんなものなんだろ?っていうのをみていこうと思います!

また、動作検証にはTinkerを使用しています。

Tinkerの使い方、見方に関しては以下を参考にしてみてください!

pluckメソッドって?

pluckメソッドは基本的には複数の配列が同じキーを持った状態で、一つのコレクションになっているところから、あるキーだけの情報をまとめて持ってきたい場合などに使えます。

例えば以下のような感じです。

>>> $collection = collect([
  ['name' => 'taka', 'age' => '25', 'occupation' => 'engineer'],
  ['name' => 'yuta', 'age' => '20', 'occupation' => 'writer'],
  ['name' => 'takapon', 'age' => '80', 'occupation' => 'singer']
]);
=> Illuminate\Support\Collection {#2982
     all: [
       [
         "name" => "taka",
         "age" => "25",
         "occupation" => "engineer",
       ],
       [
         "name" => "yuta",
         "age" => "20",
         "occupation" => "writer",
       ],
       [
         "name" => "takapon",
         "age" => "80",
         "occupation" => "singer",
       ],
     ],
   }
>>> $collection->pluck('name');
=> Illuminate\Support\Collection {#3013
     all: [
       "taka",
       "yuta",
       "takapon",
     ],
   }

名前と年齢、そして職業をキーにもつ配列が三つあり、その中からnameのキーの値のみで構成されるコレクションを作成することができます。

もちろん、"age"や"occupation"でも可能です。

配列ではない場合

では最初に気になるのが配列ではない要素で、キー名は一緒だったり、キー名が存在しないややこしい奴がいたらどうなるか?ですね。

やってみました。

>>> $collection = collect([                                                                                                                                                                                 
  ['name' => 'A'],                                                                                                                                                                                            
  'name' => 'B',                                                                                                                                                                                              
  ['age' => '20'],                                                                                                                                                                                                                                                                                                                                                                                
]);
=> Illuminate\Support\Collection {#2999
     all: [
       0 => [
         "name" => "A",
       ],
       "name" => "B",
       1 => [
         "age" => "20",
       ],
     ],
   }
>>> $collection->pluck('name');                                                                                                                                                                             => Illuminate\Support\Collection {#2977
     all: [
       "A",
       null,
       null,
     ],
   }

配列ではない場合もキーが存在しない場合もnullになっていますね。

次いってみましょ!

ネストした(深い階層にある)キーを指定する

さて、では次はネストしたものを指定する方法をみてみましょう。

$collection = collect([
  ['name' => ['first' => 'taka', 'last' => 'pon']],
  ['name' => ['first' => 'tarou', 'last' => 'yamada']],
  ['name' => ['first' => 'yuta', 'last' => 'suzuki']]
]);
=> Illuminate\Support\Collection {#3046
     all: [
       [
         "name" => [
           "first" => "taka",
           "last" => "pon",
         ]
       ],
       [
         "name" => [
           "first" => "tarou",
           "last" => "yamada",
         ]
       ],
       [
         "name" => [
           "first" => "yuta",
           "last" => "suzuki",
         ]
       ],
     ],
   }

さて、こう言う配列が入っていたらどうでしょう?

それぞれ'name'の中にさらに連想配列が入っています。

この場合、こうすれば取得ができます。

>>> $collection->pluck('name.first');
=> Illuminate\Support\Collection {#3039
     all: [
       "taka",
       "tarou",
       "yuta",
     ],
   }

ドット記法でつなげてあげればいいんですね!

ではさらにさらに...

コレクションがネストしている場合

コレクションの中にコレクションがあるケースもあるかもしれませんね。

そちらもみてみましょう。

>>> $collectionchild = $collection = collect([
   ['name' => ['first' => 'taka', 'last' => 'pon']],
   ['name' => ['first' => 'tarou', 'last' => 'yamada']],
   ['name' => ['first' => 'yuta', 'last' => 'suzuki']]
]);
...
...
>>> $collection = collect([
   ['hoge' => 'huga'],
   ['person'=> $collectionchild ]
]);
=> Illuminate\Support\Collection {#3017
     all: [
       [
         "hoge" => "huga",
       ],
       [
         "person" => Illuminate\Support\Collection {#3001
           all: [
             [
               "name" => [
                 "first" => "taka",
                 "last" => "pon",
               ],
             ],
             [
               "name" => [
                 "first" => "tarou",
                 "last" => "yamada",
               ],
             ],
             [
               "name" => [
                 "first" => "yuta",
                 "last" => "suzuki",
               ],
             ],
           ],
         },
       ],
     ],

さて、ややこしくなってきましたね。$collectionの中の二つ目の配列のキーがpersonの値にさらに$collectionchildが入っています。

この$collectionchildのキーでpluckはできるんでしょうか...?

>>> $collection->pluck('person.name.first');
=> Illuminate\Support\Collection {#3009
     all: [
       null,
       null,
     ],
   }

むむっ。どうやら'person.name.first'という指定ではだめですね...

ただ、ご安心ください...!

>>> $collection->pluck('person.*.name.first');
=> Illuminate\Support\Collection {#3014
     all: [
       null,
       [
         "taka",
         "tarou",
         "yuta",
       ],
     ],
   }

できました!

アスタリスクをつけたらいけましたね...?

ちょっとこの挙動について自分なりに考察してみます...

pluckの挙動について

さて、ここからは僕個人の推測なんですが...w

pluckではコレクションに対して、そのコレクションに入っている全ての配列を読みます。

>>> $collection = collect([
   ['name' => 'A'],
   ['name' => 'B'],
   ['age' => '20'],
   ['height' => '160']
]);
>>> $collection->pluck('name');
=> Illuminate\Support\Collection {#2993
     all: [
       "A",
       "B",
       null,
       null,
     ],
   }

上記のように、探しているのは"name"です。しかし、三つ目や四つ目の配列には"name"キーがないですね。

そのため、"null"となっています。

つまり、pluckメソッドによって...

特に指定がなくても第一階層の配列を全て捜査しているんですね。

では、先ほどのコレクションの中にコレクションがある場合を考えます。

先ほどは以下のような形(少しみやすいように省略しています)のコレクションの入れ子でした

=> Illuminate\Support\Collection {#3017   
all: [
       [
         "hoge" => "huga",
       ],
       [
         "person" => Illuminate\Support\Collection {#3001
           all: [
             [
               "name" => [
                 "first" => "taka",
               ],
             ],
             [
               "name" => [
                 "first" => "tarou",
               ],
             ]
           ],
         },
       ],
     ],

// 以下で取ってこれた
>>> $collection->pluck('person.*.name.first');

ではこれを指定する場合を考えてみます。

まず、最初にpersonを探したいですね。

先ほど述べたとおり、$collectionの直下の配列を全てpluckメソッドで探すことができます。

そして、次に見つけたpersonの中身もcollectionでした。

そのcollectionの中身にももちろん、複数の配列が入ってくる可能性がありますよね?

もしも"person.name"だと、いや、どの配列だよ!ってなってしまいません?

そうなんです。pluckで最初のコレクションは全て捜査できたんですが、二つ目いこうのネストしたコレクションは全て捜査できません。

そこで、ワイルドカード(*)をつかって、この"コレクション配下全ての"という条件をつけてあげないといけないわけです。

そうなると'person.*.name.first'でうまくいったことも納得ですね!

まとめ

ネストしたコレクションのpluckってそもそもできるっけ・・・?

って調べると意外と少ない少ない...

ドット記法でできることすらあまり書かれていなかったので、結構大変でした...w

一番いいのはフレームワーク自体のコードをみて理解できたらいいんでしょうけども...流石にそこまでは...w

皆さんもpluckで困ったら是非ご参考にしてみてくださいね!

それでわ!

おすすめの記事