【Laravel9】Collectionクラスの中身を見る~onlyメソッド編~
はじめに
配列を操作するためのラッパークラスであるIlluminate\Support\CollectionクラスにはLaravel9では139個ものメソッドがあります。
Laravelを使用していたら見かけるであろう、map()やpluck()、merge()はCollectionクラスのメソッドです。
公式ドキュメントも貼っておきます。
今回はonlyメソッドが何をしているのか見ていきます。
環境
- Windows11(WSL2)
- PHP 8.2.1
- Laravel 9.50.1
- sail 2.6.1
onlyメソッドとは
only()はコレクションの中から指定したアイテムだけを返すメソッドです。
動作確認
$collect = collect([
'name' => 'A',
'height' => 175,
'weight' => 70,
'gripStrength' => 55,
]);
$result = $collect->only(['name', 'weight']);
dd($result);
nameとweightをキーとするアイテムのみ返ってきます。
Illuminate\Support\Collection {#275 ▼
#items: array:2 [▼
"name" => "A"
"weight" => 70
]
#escapeWhenCastingToString: false
}
onlyメソッドの中身
Illuminate\Support\Collection::only
Collectionクラスのonlyメソッドのは以下のようになっています。
public function only($keys)
{
//①
if (is_null($keys)) {
return new static($this->items);
}
//②
if ($keys instanceof Enumerable) {
$keys = $keys->all();
}
//③
$keys = is_array($keys) ? $keys : func_get_args();
//④
return new static(Arr::only($this->items, $keys));
}
①引数$keysにnullが渡ってきたときはコレクションをそのまま返します。
②Enumerableはインターフェースなので、$keysのインスタンスがEnumerableインターフェースを継承しているクラスであればtrueになり、そのクラスのallメソッドを返します。
例えば、Illuminate\Support\CollectionクラスはEnumerableインターフェースを継承しているので$collect->only(collect(['name']))
のような引数を入れても動作します。
③引数$keysが配列である場合は問題ないとして、配列でない場合はfunc_get_args()
が呼び出されています。
func_get_args()は不特定の数の引数を配列として受け取ることができる関数です。
そのため$collect->only('name', 'height')
と配列でない引数を渡しても③のところで$keysへ配列にして渡してくれます。
④Illuminate\Support\Arrクラスのonlyメソッドをインスタンス化してreturnしているので、追ってみます。
Illuminate\Support\Arr::only
Arrクラスのonlyメソッドは以下のようになっています。
public static function only($array, $keys)
{
return array_intersect_key($array, array_flip((array) $keys));
}
array_intersect_key()は複数の配列の中から共通のキー名を見つけて、その共通のキーの配列を返す関数です。
引数に3つ以上配列を入れても全ての配列の共通キーを探します。
配列同士のキーを比較したいのですが、$keysは
array:2 [▼
0 => "name"
1 => "height"
]
となっています。そのためarray_flip()でキーと値を反転させてあげます。
これでコレクションから引数で指定したキーのみを返すようになります。
まとめ
Collectionクラスのonlyメソッドでは、内部的にIlluminate\Support\Arrのonlyメソッドを呼んでいて、
標準関数のarray_intersect_key()やarray_flip()を使用していることが分かりました。
Discussion