目次
1. はじめに
Laravelを使っていて、複雑な配列からデータを抽出する際にCollectionに関するエラーに遭遇したことはありませんか?
本記事では、Collectionってそもそも何?どういうメリットがあるの?よく遭遇するエラーは?といったところをまとめた記事にしたいと思います。
2. Collectionとは?
LaravelのCollectionは、配列をより便利に扱うためのラッパークラスです。
通常のPHPの配列ではなく、Collectionを使うことでメソッドチェーンを活用しながら直感的にデータ操作ができます。
配列とCollectionの比較
項目 | PHPの配列 | LaravelのCollection |
---|---|---|
型 | 配列 (array ) |
Illuminate\Support\Collection クラス |
操作方法 | array_map(), array_filter() など | メソッド (map(), filter() など) |
メソッドチェーン | ❌ 不可 | ✅ 可能 |
高度なデータ操作 | ❌ 手動実装が必要 | ✅ 多くの便利メソッドあり |
変更後のデータ | 直接変更 | 新しいCollectionを返す |
- ラッパークラス
⇒基本データ型や既存のデータ構造をオブジェクトとして扱うためのクラスのこと。 - メソッドチェーン
⇒オブジェクト指向プログラミングで複数のメソッドを連続して呼び出す書き方のこと
Collectionの生成
use Illuminate\Support\Collection;
// collect()関数を使用して、配列をCollectionオブジェクトに変換
$collection = collect([1, 2, 3, 4, 5]);
dump($collection);
/* 出力結果
Illuminate\Support\Collection {#1234
#items: array:5 [
0 => 1
1 => 2
2 => 3
3 => 4
4 => 5
]
}
*/
解説
- Illuminate\Support\Collection {#1234}
→ Collection クラスのインスタンスであることを示します。(#1234 はオブジェクトIDなので実行ごとに変わる) - #items: array:5
→ Collection 内部で管理されている配列データ ([1, 2, 3, 4, 5]) が表示される。 - 0 => 1, 1 => 2, ...
→ 配列のキーと値がリスト形式で表示される。
3. よく使うコレクションメソッド16選
1. map()
コレクション内の各要素に処理を行い、新しいコレクションを返す。
$numbers = collect([1, 2, 3]);
$mapped = $numbers->map(fn($num) => $num * 2);
print_r($mapped->all()); // [2, 4, 6]
2. filter()
コレクション内の要素を条件でフィルタリングし、新しいコレクションを返す。
$numbers = collect([1, 2, 3, 4, 5]);
$filtered = $numbers->filter(fn($num) => $num % 2 === 0);
print_r($filtered->all()); // [2, 4]
3. reduce()
コレクションのすべての要素を1つの値にまとめる。
合計だけでなく、最小値や最大値、その他の演算にも利用可能。
$numbers = collect([1, 2, 3]);
$sum = $numbers->reduce(fn($carry, $num) => $carry + $num, 0); // 合計を計算する例
echo $sum; // 6
4. pluck()
コレクションの要素から指定したキーの値を取り出す。
$products = collect([
['name' => 'Apple', 'price' => 100],
['name' => 'Banana', 'price' => 150],
]);
$prices = $products->pluck('price');
print_r($prices->all()); // [100, 150]
5. sort() / sortBy()
コレクションを昇順に並べ替えする。
$numbers = collect([5, 1, 3, 2, 4]);
$sortedNumbers = $numbers->sort();
print_r($sortedNumbers->all()); // [1, 2, 3, 4, 5]
sortBy() は、指定したキーで並べ替えする。
下記の例は、'price'を基準に昇順にソートしている。
$products = collect([
['name' => 'Banana', 'price' => 150],
['name' => 'Apple', 'price' => 100],
]);
$sortedByPrice = $products->sortBy('price');
print_r($sortedByPrice->values()->all());
/* 出力結果
Array
(
[0] => Array
(
[name] => Apple
[price] => 100
)
[1] => Array
(
[name] => Banana
[price] => 150
)
)
*/
6. first()
コレクションの最初の要素を返す。
$numbers = collect([1, 2, 3, 4, 5]);
$firstNumber = $numbers->first();
echo $firstNumber; // 1
7. each()
コレクションの各要素に処理を実行する。戻り値は元のコレクション。
map()と似ているが、eachの場合、新しいコレクションは返さず出力のみ行う。
$numbers = collect([1, 2, 3]);
$numbers->each(fn($num) => print($num * 2)); // 出力: 2, 4, 6
8. groupBy()
コレクションを指定したキーでグループ化する。
$products = collect([
['name' => 'Apple', 'category' => 'Fruit'],
['name' => 'Banana', 'category' => 'Fruit'],
['name' => 'Carrot', 'category' => 'Vegetable'],
]);
$grouped = $products->groupBy('category');
print_r($grouped->all());
/* 出力結果
Array
(
[Fruit] => Array
(
[0] => Array
(
[name] => Apple
[category] => Fruit
)
[1] => Array
(
[name] => Banana
[category] => Fruit
)
)
[Vegetable] => Array
(
[0] => Array
(
[name] => Carrot
[category] => Vegetable
)
)
)
*/
9. toArray()
コレクションを配列に変換します。
$numbers = collect([1, 2, 3]);
$array = $numbers->toArray();
print_r($array); // [1, 2, 3]
10. contains()
コレクションに指定した値が含まれているかをチェックします。
$numbers = collect([1, 2, 3, 4, 5]);
$isPresent = $numbers->contains(3); // true
echo $isPresent;
11. count()
コレクション内の要素数を返します。
$numbers = collect([1, 2, 3, 4, 5]);
$count = $numbers->count();
echo $count; // 5
12. unique()
コレクション内の重複を排除し、ユニークな要素だけのコレクションを返します。
$numbers = collect([1, 2, 2, 3, 3, 3, 4]);
$unique = $numbers->unique();
print_r($unique->all()); // [1, 2, 3, 4]
13. flatten()
コレクションの多次元配列を1次元に平坦化します。
$numbers = collect([[1, 2], [3, 4], [5, 6]]);
$flattened = $numbers->flatten();
print_r($flattened->all()); // [1, 2, 3, 4, 5, 6]
14. keyBy()
コレクション内の要素を指定したキーでインデックス化します。
$products = collect([
['id' => 1, 'name' => 'Apple'],
['id' => 2, 'name' => 'Banana'],
]);
$keyed = $products->keyBy('id');
print_r($keyed->all());
/* 出力結果
Array
(
[1] => Array
(
[id] => 1
[name] => Apple
)
[2] => Array
(
[id] => 2
[name] => Banana
)
)
*/
15. forget()
コレクションから指定したキーの要素を削除します。
$numbers = collect([1, 2, 3, 4, 5]);
$numbers->forget(2); // 3番目の要素(インデックス2)を削除
print_r($numbers->all()); // [1, 2, 4, 5]
16. sum()
コレクション内の合計値を取得します。
$numbers = collect([1, 2, 3, 4, 5]);
$total = $numbers->sum();
echo $total; // 15
4. 実践的な使用例
4.1 APIレスポンスの整形
LaravelのCollectionはAPIレスポンスの整形に非常に便利!!
APIから取得した生データを必要な形式に整形する際に使用する。
例: ユーザーのAPIレスポンスを整形
use Illuminate\Support\Collection;
$users = collect([
['id' => 1, 'name' => 'John', 'email' => 'john@example.com'],
['id' => 2, 'name' => 'Jane', 'email' => 'jane@example.com'],
]);
// ユーザーの名前とメールアドレスだけを取得
$transformed = $users->map(function ($user) {
return [
'user_name' => $user['name'],
'user_email' => $user['email']
];
});
// JSONレスポンスとして返却
return response()->json($transformed);
4.2 よくあるエラーと対処法
LaravelのCollectionを扱う際によく発生するエラーと、その対処法について。
4.2.1 Call to undefined function collect() エラー
エラー内容
$collection = collect([1, 2, 3, 4, 5]);
Call to undefined function collect()
原因
collect()はLaravelの Illuminate\Support\Collectionクラスの関数であるが、
Laravel以外の環境(純粋なPHPスクリプトなど)では利用できません。
対処法
Laravelのフレームワークを正しくロードしているか確認する。
または、手動でCollectionクラスをインポートする。
use Illuminate\Support\Collection;
$collection = new Collection([1, 2, 3, 4, 5]);
4.2.2 Trying to get property of non-object エラー
エラー内容
$collection = collect([
['id' => 1, 'name' => 'Alice'],
['id' => 2, 'name' => 'Bob'],
]);
$names = $collection->map(function ($user) {
return $user->name; // ここでエラー
});
Trying to get property of non-object
原因
$userは配列なのに、
$user->nameとオブジェクトのプロパティにアクセスしようとしている。
対処法
配列のキーを使ってアクセスするように修正。
$names = $collection->map(function ($user) {
return $user['name']; // 正しく配列のキーを指定
});
もしオブジェクトとして扱いたい場合は、キャストするかcollect()にtoObject()を適用する。
$collection = collect([
(object) ['id' => 1, 'name' => 'Alice'],
(object) ['id' => 2, 'name' => 'Bob'],
]);
$names = $collection->map(function ($user) {
return $user->name; // 正常に動作
});
4.2.3 Collection::map() の返り値が意図しない型になる
エラー内容
$collection = collect([1, 2, 3]);
$collection->map(function ($item) {
echo $item * 2;
});
// 出力結果
246
原因
map()は新しいCollectionを返すが、
上記のコードではechoしているため、返り値がnullになり、意図しない結果になる。
対処法
新しい値をreturnするように修正。
$modified = $collection->map(function ($item) {
return $item * 2;
});
dump($modified->all()); // [2, 4, 6]
4.2.4. Undefined array key エラー
エラー内容
$collection = collect([
['id' => 1, 'name' => 'Alice'],
['id' => 2] // 'name' キーがない
]);
$names = $collection->map(function ($user) {
return $user['name']; // 'name' キーが存在しない場合にエラー
});
Undefined array key "name"
原因
配列の中に 'name'キーがない要素があるため、アクセス時にエラーが発生。
対処法
キーが存在するかチェックしてからアクセスする。
$names = $collection->map(function ($user) {
return $user['name'] ?? 'No Name'; // デフォルト値を設定
});
4.2.5. Cannot use object of type stdClass as array エラー
エラー内容
$collection = collect([
(object) ['id' => 1, 'name' => 'Alice'],
(object) ['id' => 2, 'name' => 'Bob'],
]);
$names = $collection->map(function ($user) {
return $user['name']; // エラー発生
});
Cannot use object of type stdClass as array
原因
$userはオブジェクトなのに、配列のように['name']でアクセスしようとしている。
対処法
オブジェクトのプロパティとしてアクセスする。
$names = $collection->map(function ($user) {
return $user->name; // 正しい書き方
});
もし配列として扱いたい場合は、オブジェクトを配列に変換する。
$collection = $collection->map(function ($user) {
return (array) $user;
});
5. まとめ
業務では既にcollectionが使われている箇所の改修を任されたため、
複数のメソッドを連続して簡潔にソースを書くことができるということを知りませんでした。
今回はCollectionの基本から学ぶことができたので、
複雑な配列からデータを取得する際や、Collectionに関するエラーに遭遇した際などに今回学んだことを役立てたいと思います。