みなさん、初めまして
learningBOX株式会社の開発部開発課に所属している末廣と申します。
突然ですが、みなさんはPHPのArrayは好きでしょうか。
私は嫌いです(ドン)
Arrayが嫌いな理由を説明します。
array_*****
関数の引数の位置がバラバラarray_column()
とarray_filter()
は引数の1個目にArrayを指定するが、in_array()
やarray_map()
は引数の2個目にArrayを指定するarray_*****
関数の実行結果の取得方法がバラバラarray_unique()
は結果が戻り値で返ってくるが、array_push()
は引数が参照渡しされており引数のArrayが直接書き換わるarray_map()
などを入れ子にした場合の可読性が悪いarray_map()
やarray_filter()
などを入れ子にしたコードは可読性が悪く、何をやっているかの解読に時間がかかります- 配列と連想配列の区別ができない
Arrayを多用する影響で新機能実装時には問題はないが、機能改修時にバグ混入のリスクなど様々な問題が顕在化してきました。
そこでArrayの問題点を解消するために、Collectionを導入したいと思うようになりました。
Collectionとは
Arrayを直接操作するのではなく、Collectionという型にラップして様々な操作をするもの。
PHPには前述のArrayの問題があることから、Laravel、CakePHP、Symfonyなど主要なモダンPHPフレームワークには全てでCollectionが実装されている。
learningBOXでは独自フレームワークを採用していますが、Collection機能は存在しないため今までは生PHPのArrayで頑張っていました。
何か良い方法はないかと思っていた所、Laravelのフレームワークとしての導入はせずに、Collection機能のみ導入できることがわかったので導入してみることにしました。
導入方法
Laravelのヘルパの集合をComposerでインストールします。
Collectionだけでなく他のヘルパもインストールされますので、その点だけご注意ください。
composer require illuminate/support
使い方
collect()
というヘルパが用意されており、基本的にcollect()
の引数にArrayを渡すことで使用が可能になります。
戻り値でCollectionを受け取ってから記述もしくは、そのままメソッドチェーンで書いたりします。CollectionからArrayに戻すためには、toArray()
メソッドで変換する必要がありますので、ご注意ください。
比較
Array関数を使って実装
$arr = [1, 2, 3, 4, 5];
$calced = array_reduce(
array_filter(
array_map(
fn ($v) => $v * $v,
$arr
),
fn ($v) => $v < 10
),
fn ($a, $b) => $a + $b
);
var_dump($calced);
Collectionを使って実装
$arr = [1, 2, 3, 4, 5];
$calced = collect($arr)->map(fn($v) => $v * $v)
->filter(fn($v) => $v < 10)
->reduce(fn($a, $b) => $a + $b);
var_dump($calced);
比べてみてどうでしょうか?
明らかにArray関数を使った場合よりも、Collectionを使った場合の方が簡潔かつ可読性が高いです。
他にもCollectionには便利な関数が色々用意されています。
代表的なものをいくつか紹介します。
引用元:Laravel 9.x Collections
オススメの使い方
Laravel Collectionは非常に便利ではあるのですが、各メソッドが多機能かつ数が多いので全てを把握するのがなかなか辛く、各ユースケースへのベストな使い方が難しかったりします。
そんな時に個人的にオススメの使い方を紹介したいと思います。
雑にforeach
を使って実装して、ChatGPTを使ってLaravel Collectionを使った実装に直してもらう方法です。
こんな感じで、そこそこ的確なコードに書き直してくれます。
おそらくGoogle Bardなどでもできるので、使える方は是非試してみてください。
以上、フレームワークを導入せずにCollectionだけ導入する方法の紹介でした。
モダンフレームワークを導入していないが、Collectionを使って見たい方は是非参考にしてください。
Q:普通にLaravel導入すれば良かったのでは
A:FW載せ替える工数が無かったのだよ
バックエンド全体としてはまだまだレガシーですが、新しい提案は比較的通りやすい環境です。
レガシーからモダンなバックエンドにする過程を経験してみたいという方は是非一緒に改善していきましょう。