
[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で補完されないようです。