きっかけ
2次元配列で、中身の配列の順序を入れ替えるという汎用的な共通処理を追加したかったのだが、ユーティリティクラスを作るか、ファサードで実装するかなど迷っていた。
Laravelには配列を扱うヘルパー関数がすでにある
よくよく考えると、LaravelにはArrという標準で配列を操作するヘルパー関数が存在するので、同じように配列を操作するヘルパー関数クラスを別途に作るのはナンセンス過ぎると判断。そこでArrヘルパー関数を拡張することにした。
Arrヘルパー関数の拡張
ヘルパー関数の拡張にはマクロを使用する。マクロの説明については以下を参照されたい。
既存のサービスプロバイダを汚さないように。専用のプロバイダを用意する。
bootクラスにマクロを使った拡張メソッドを実装する。
<?php
namespace App\Providers;
use Illuminate\Support\Arr;
use Illuminate\Support\ServiceProvider;
class ArrayMacrosServiceProvider extends ServiceProvider
{
public function register(): void
{
//
}
public function boot(): void
{
Arr::macro('swap', function ($array, $index1, $index2):array
{
if (isset($array[$index1], $array[$index2])) {
list($array[$index1], $array[$index2]) = [$array[$index2], $array[$index1]];
}
return $array;
});
}
}
続いて、config/app.php
のprovidersに登録する。
'providers' => ServiceProvider::defaultProviders()->merge([
/*
* Package Service Providers...
*/
/*
* Application Service Providers...
*/
//色々なサービスプロバイダが登録されている・・・
App\Providers\ArrayMacrosServiceProvider::class,//ここに追加
])->toArray(),
以下のように利用できるようになる。
最初に第一パラメータを参照渡しにしていたが、これはうまく動かなかった。
※参照渡しにこだわる理由もなかったので、入れ替えごの配列を返す形に変更した。
$items = Arr::swap($items, $index1, $index2);
同じような責任を持つクラスが重複するのは、車輪の再発明(Reinventing the wheel)にも通ずるところがある。クラスの膨張(Class Bloat)にも繋がるので、注意したいところ。