概要
Laravel best practices for 2022
のController、Eloquent関連をピックアップします(deeplぶち込み翻訳)
既存のベストプラティクス
こちらの方が内容も濃い気がするのでまずはこちらを
カスタムフォームリクエストを使用する
カスタムフォームリクエストを使用する主な理由は以下のとおりです。
- 複数のコントローラでバリデーションを再利用する。
- 肥大化したコントローラからコードをオフロードする。
カスタムフォームリクエストの作成は、以下のArtisanコマンドを実行することで簡単に行えます。
php artisan make:request StorePostRequest
そして、コントローラーで、タイプ・ヒントを出すだけです。
use App\Http\Requests\StorePostRequest;
class PostController
{
function store(StorePostRequest $request)
{
$validated = $request->validated();
Post::create($validated);
//
}
}
カスタムリクエストも認可に使えますが、私はポリシーに頼る方が好きです。
ポリシーの使用
ポリシーが存在する理由はいくつかあります。
- 複数のコントローラで認可ロジックを再利用する。
- 肥大化したコントローラからコードをオフロードする。
- 認可に関連するすべてのものを app/Policies フォルダでチェックアウトすることは、誰にとっても自然なことです。
シングルアクションコントローラの使用
シングルアクションコントローラの使用
ベストプラクティスに従ったにもかかわらず、コントローラが大きくなりすぎることがあります。
Laravelには、これを解決するための方法があります。シングルアクションコントローラーです。
リソースコントローラのように複数のアクションを含むのではなく、シングルアクションコントローラは1つだけ含みます。
これを作成するには、
php artisan make:controller ShowPostController --invokable
コマンドを使用します。
これにより、__invoke という名前のアクションをひとつだけ持つコントローラが作成されます (マジックメソッドの __invoke についてはこちらを参照ください)。
そして、Routesの中で、代わりにこのようなことができるようになります。
- use App\Http\Controllers\PostController;
+ use App\Http\Controllers\ShowPostController;
- Route::get('/posts/{post}', [PostController::class, 'show']);
+ Route::get('/posts/{post}', ShowPostController::class);
イーガーローディングによるN+1問題の防止
N+1問題が発生しないようにするために、リレーションシップをダラダラロードするたびに例外を発生させることができます。
この制限は、あなたのローカル環境のみに適用されるべきです。
Model::preventLazyLoading(
! app()->isProduction()
);
Eloquentのストリクトモードを使用する
Eloquentのstrictモードは、デバッグにはありがたい。以下のような場合に例外を投げます。
- リレーションシップのレイジーローディング
- 記入不可能な属性の割り当て
- 存在しない(または取得されなかった)アトリビュートにアクセスする場合。
AppServiceProvider.php の boot() メソッドに、次のコードを追加してください。
Model::shouldBeStrict(
! app()->isProduction() // Only outside of production.
);
アクセサとミューテータの新しい宣言方法を使用する
Laravel 9では、アクセサとミューテータの新しい宣言方法が導入されました。
現在では、このように宣言する必要があります。
use IlluminateDatabaseEloquentCastsAttribute;
class Pokemon
{
function name() : Attribute
{
$locale = app()->getLocale();
return Attribute::make(
get: fn ($value) => $value[$locale],
set: fn ($value) => [$locale => $value],
);
}
}
計算するのに高価な値をキャッシュすることも可能です。
use IlluminateDatabaseEloquentCastsAttribute;
function someAttribute() : Attribute
{
return Attribute::make(
fn () => /* Do something. */
)->shouldCache();
}