【Laravel】バリデーションのアクションを指定する
やりたいこと
Laravel はMVCベースのフレームワークにもかかわらず、モデルの扱いは良い意味で適当で7.x以前までは配置するディレクトリすらも適当でした。そのせいもあってか、4.xまではバリデーションはコントローラにアドホックに記述するしかなくロジックが分散しがちでした。5.xからはフォームリクエストバリデーションという仕組みが導入され、リクエストにバリデーションロジックを付加しカプセル化することが可能になりました。Ruby on Rails等のフレームワークに親しい人はこの仕組を用いて、例えばUserRequest
とかArticleRequest
といった具合にモデル毎にバリデーションロジックをまとめる事ができるようになって安堵したことでしょう。
バリデーションロジックをまとめたことで、次に出てくる当然の要求はRuby on Railsのバリデーションのon
オプションの様にアクションによってそのバリデータを使い分けたいということです。つまり、例えばArticle
モデルでは記事のタイトル(title
)はstore
の時点では必須(required
)としたいが、update
のタイミングでは空でも良い(つまりタイトルは更新しないことを意味する)といった状況です。これはRuby on Railsでは
validates: title, presence: { on: create }
のように、バリデータpresence
をon
オプションでcreate
(Laravelでいうところのstore
)時に限定しています。これです。これが Laravel でもやりたいのです。
結論
Laravelには(少なくとも9.xまでには)Railsのon
オプションのような便利な機能はなさそうです。でも殆どのバリデータは共通なのに、そのうちの限られたフィールドに関するバリデータが異なるからといってArticleStoreRequest
、ArticleUpdateRequest
のようにアクション毎にフォームリクエストを分けていては本末転倒です。(それならコントローラに直接バリデーションを記述した方がよっぽどわかりやすいと筆者は考えます。)
Laravelでこのstore
時のみもしくはupdate
時のみに作用するバリデータを記述するには、Route
ファサードを使用するのが便利だと思います。書き方は以下のようになります。
return [
'title' => \Route::uses('*store') ? 'required' : 'filled',
];
もちろんフォームリクエストのrules
メソッドの返り値として記述することを想定しています。Route
ファサードのuses
メソッドはApp\Http\Controllers\ArticleController@store
のような「コントローラ@アクション」という文字列に対してStr::is
ヘルパで検査をしますのでワイルドカード(*
)が使用できます。詳しくはAPIを確認してください。
ちなみに上記のfilled
バリデータは、そのフィールドが存在しなくてもOKだが存在するならば空であってはならないという検証を実行します。つまり上記のようなルールを設定すると、新規作成時にはtitle
フィールドは指定されなければならず、さらに空文字や空白のみで構成されるような文字列も却下しますが、更新時にはtitle
フィールドは指定されなくても許容します。ただし、指定された時にはそれは空文字や空白のみの文字列では許されません。
参考文献
Author And Source
この問題について(【Laravel】バリデーションのアクションを指定する), 我々は、より多くの情報をここで見つけました https://qiita.com/chiyo_i/items/aeb00305c1a79fec8793著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .