[Laravel] Macroableを使ってクラスを拡張する
LaravelのMacroable
トレイトを使ったクラスの拡張について。
Illuminate\Support\Traits\Macroable
をuseするとClass::macro(method, callback)
として既存のクラスにメソッドを拡張することができます。
公式では実装済みのCollection
クラスにでの使い方が記されており、独自のメソッドを追加できるようになっています。
use Illuminate\Support\Str;
Collection::macro('toUpper', function () {
return $this->map(function ($value) {
return Str::upper($value);
});
});
$collection = collect(['first', 'second']);
$upper = $collection->toUpper();
// ['FIRST', 'SECOND']
また、コントローラーでリクエストされた値に対しての評価をする方法として下記があります。
/**
* Store a new blog post.
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
$validatedData = $request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
// The blog post is valid...
}
このvalidate()
メソッドは下記のようにMacroable
トレイトを使って定義されています。
Illuminate\Http\Request
にIlluminate\Support\Traits\Macroable
をuseしてメソッドの拡張を可能にIlluminate\Foundation\Providers\FoundationServiceProvider
でmacro で登録
// laravel/framework/src/Illuminate/Foundation/Providers/FoundationServiceProvider.php
/**
* Register the "validate" macro on the request.
*
* @return void
*/
public function registerRequestValidate()
{
Request::macro('validate', function (array $rules, ...$params) {
validator()->validate($this->all(), $rules, ...$params);
return $this->only(collect($rules)->keys()->map(function ($rule) {
return str_contains($rule, '.') ? explode('.', $rule)[0] : $rule;
})->unique()->toArray());
});
}
Macroable
トレイトのデメリットとしては、ServiceProvider
等を使わずに拡張しすぎると見通しが悪くなってしまう点と、barryvdh/laravel-ide-helper
で補完されないようです。