Laravel の Collection について

Laravel の使える機能の一つが Collection (コレクション) です。

PHP のプログラミングは「配列だらけ」と言われるとおり、配列操作がとても多いです。

Laravel の Collection はその 手間を軽減しますが、同時にコード量が減って見通しもよくなるためメリットが多い と感じます。
実際ほぼ Collection で OK な感じがしますね。

たとえば、どんな

「ユーザテーブルを SELECE して ID 一覧を取得したい」とします。

よくある PHP のコードは次のようになりますね。

1$users = User::all();
2
3$userIds = [];
4foreach ($users as $user) {
5    $userIds[] = $user->id;
6}

Collection に置き換えるとこうなります。

1$users = User::all();
2$userIds = $users->pluck('id');

Laravel の Eloquent ORM では問い合わせ結果を Collection に詰めて返却します。

無名関数を組み合わせて

Collection は、メソッドの引数に無名関数を渡すことができます。

1$sortedEntities = $entities->sort(function($first, $second) {
2     return $first->price <=> $second->price
3         ?: $second->id   <=> $first->id;
4  });

無名関数を併用すると、さらに柔軟なコーディングができます。

ドキュメント

Laravel 5.5 Collections
https://laravel.com/docs/5.5/collections

メソッド紹介

コレクションはメソッドがとても豊富です。
ここでは私がよく使うものをピックアップいたします。

また、以下に示すサンプルは大部分を上記ドキュメントから引用いたします。

contains

contains メソッドは「指定したアイテムがコレクションに含まれているか」を判定します。

1$collection = collect(['name' => 'Desk', 'price' => 100]);
2
3$collection->contains('Desk');
4
5// true

連想配列の value を調べていますね。 配列の形に注意が必要そうです。

where

where メソッドは「指定した key/value のペア」でコレクションをフィルタリングします。

 1$collection = collect([
 2    ['product' => 'Desk', 'price' => 200],
 3    ['product' => 'Chair', 'price' => 100],
 4    ['product' => 'Bookcase', 'price' => 150],
 5    ['product' => 'Door', 'price' => 100],
 6]);
 7
 8$filtered = $collection->where('price', 100);
 9
10$filtered->all();
11
12/*
13    [
14        ['product' => 'Chair', 'price' => 100],
15        ['product' => 'Door', 'price' => 100],
16    ]
17*/

これは DB 操作と近い感覚ですね。

take / slice

take は先頭から n個 のコレクションを返します。

1$collection = collect([0, 1, 2, 3, 4, 5]);
2
3$chunk = $collection->take(3);
4
5$chunk->all();
6
7// [0, 1, 2]

n を負で指定した場合は後ろから n個 の要素を返します。


おなじようなメソッドに slice があります。 これは「指定したインデックスからコレクションを切り分け」ます。

第一引数のみの場合、指定値から後ろをすべて返します。

1$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
2
3$slice = $collection->slice(4);
4
5$slice->all();
6
7// [5, 6, 7, 8, 9, 10]

第二引数を与えた場合、指定値から n件 を返します。

1$slice = $collection->slice(4, 2);
2
3$slice->all();
4
5// [5, 6]

chunk

chunk は「コレクションを固まりごと」に操作します。

1$collection = collect([1, 2, 3, 4, 5, 6, 7]);
2
3$chunks = $collection->chunk(4);
4
5$chunks->toArray();
6
7// [[1, 2, 3, 4], [5, 6, 7]]

メモリサイズを気にする場合など、小さなブロックごとに処理できるのでいい感じです。

keyBy

keyBy は「指定したキーをコレクションのキー」にします。

 1$collection = collect([
 2    ['product_id' => 'prod-100', 'name' => 'Desk'],
 3    ['product_id' => 'prod-200', 'name' => 'Chair'],
 4]);
 5$keyed = $collection->keyBy('product_id');
 6
 7$keyed->all();
 8/*
 9    [
10        'prod-100' => ['product_id' => 'prod-100', 'name' => 'Desk'],
11        'prod-200' => ['product_id' => 'prod-200', 'name' => 'Chair'],
12    ]
13*/

私は ID をキーとしたマップを作る場合に多用します。

keyBy は「 1 対 1 」の関係を表現するため、 同じキーが存在する場合に、上書きされてしまう 点に注意が必要です。 Key の重複がある場合は groupBy を使います。

groupBy

groupBy は「指定したキーによりコレクションのアイテムをグループにまとめ」ます。

 1$collection = collect([
 2    ['account_id' => 'account-x10', 'product' => 'Chair'],
 3    ['account_id' => 'account-x10', 'product' => 'Bookcase'],
 4    ['account_id' => 'account-x11', 'product' => 'Desk'],
 5]);
 6
 7$grouped = $collection->groupBy('account_id');
 8
 9$grouped->toArray();
10
11/*
12    [
13        'account-x10' => [
14            ['account_id' => 'account-x10', 'product' => 'Chair'],
15            ['account_id' => 'account-x10', 'product' => 'Bookcase'],
16        ],
17        'account-x11' => [
18            ['account_id' => 'account-x11', 'product' => 'Desk'],
19        ],
20    ]
21*/

groupBy は「 1 対多」の関係を表現するため、keyBy とはデータ構造が異なり、子が深くなる点に注意が必要です。

pluck

pluck は「指定したキーの全コレクション値」を取得します。

 1$collection = collect([
 2    ['product_id' => 'prod-100', 'name' => 'Desk'],
 3    ['product_id' => 'prod-200', 'name' => 'Chair'],
 4]);
 5
 6$plucked = $collection->pluck('name');
 7
 8$plucked->all();
 9
10// ['Desk', 'Chair']

テーブルの SELECT 結果から ID の配列を取るような時に多用します。

Laravel ではないプロジェクトに導入する

Laravel ではないプロジェクトでも Collection は利用できます。

illuminate/support
https://github.com/illuminate/support

次のように Composer コマンドでパッケージをインストールしてくださいね。

1composer require illuminate/support

おわりに

今回ご紹介した他にも、追加、削除、集計関数、差分、コールバック、一次元化 (構造変更)など、提供される機能は多岐にわたっています。

Collection をうまく使いこなせると、簡潔で見やすいソースを書くことができます。
快感です。

便利な Collection をぜひ触ってみてください。

PHPフレームワーク Laravel Webアプリケーション開発 バージョン5.5 LTS対応

竹澤 有貴,栗生 和明,新原 雅司,大村 創太郎
出版社:ソシム  発売日:2018-09-26

Amazonで詳細を見る

PHPフレームワーク Laravel入門

掌田津耶乃
出版社:秀和システム  発売日:2017-09-16

Amazonで詳細を見る

初めてのPHP

David Sklar
出版社:オライリージャパン  発売日:2017-03-18

Amazonで詳細を見る

この記事の著者 Webrow (うぇぶろう)
Web アプリ開発、 Web 顧問 エンジニア、WordPress サポートいたします。