今回は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で困ったら是非ご参考にしてみてくださいね!
それでわ!