# Babel7 OptionalChainingでLaravelのバリデーションをハンドリングする
こんにちは、@kotamatです。
昨日Babel7がリリースされましたね🎉
https://babeljs.io/blog/2018/08/27/7.0.0
Babel6から3年かかってのリリースです。コントリビューターの方々お疲れ様でした。 パッケージ名からの破壊的変更が入っていますが、babelのupgrade用スクリプトが用意されているので、手軽にupgradeすることができます(執筆時点だと、beta版までしかあげられませんが‥)
Babel7のリリースに伴い、TS39の新しいシンタクスがサポートされ、その中でもStage1のOptional Chainingが、Laravelのエラーハンドリングにとても相性がいいので紹介させていただきます。
Laravelのバリデーションエラー
Laravel側でFormRequestを用いて下記のようなバリデーションルールを実装した場合、
class StoreRelationRequest extends FormRequest { /** * Get the validation rules that apply to the request. * * @return array */ public function rules() { return [ 'address.prefecture' =>['required', 'string'], 'address.zipcode' =>['required', 'integer'], 'staff.*.id' =>['required', 'integer'], 'staff.*.name' =>['required', 'string'], ]; } }
staffの0, 1がバリデーションに引っかかった場合、下記のようなバリデーションメッセージが帰ってきます
{ "address.prefecture": ["The prefecture field is required."], "address.zipcode": ["The zipcode field is required."], "staff.0.id": ["The id field is required."], "staff.0.name": ["The name field is required."], "staff.1.id": ["The id field is required."], "staff.1.name": ["The name field is required."] }
このままでは、フロント側では扱いづらいので、フロント側で扱いやすい形に整形します
reno-shelter/convert-laravel-validationを使うと、上記メッセージは下記のように修正されます
{ address: { prefecture: ['The prefecture field is required.'], zipcode: ['The zipcode field is required.'], }, staff: { 0: { name: ['The name field is required.'], id: ['The id field is required.'], }, 1: { name: ['The name field is required.'], id: ['The id field is required.'], }, }, }
Optional Chainingでメッセージを取り扱う
上記オブジェクトでは、例えば、address.*系のエラーがない場合は、当然ながら参照できない形になってしまうため、メッセージ表示部分で存在可否のチェックを行わないとundefined indexのFatal Errorが発生してしまいます。
そこで便利なのがOptionalChainingです。
Optional chainingの仕組み
const obj = { foo: { bar: { baz: 42, }, }, }; const baz = obj?.foo?.bar?.baz; // 42 const safe = obj?.qux?.baz; // undefined // Optional chaining and normal chaining can be intermixed obj?.foo.bar?.baz; // Only access `foo` if `obj` exists, and `baz` if // `bar` exists
このように、存在しないパラメータがチェーンの途中にあるばあいは、そこでundefinedを返し、ランタイムでのエラーを防ぐ事ができます。
<template> <div> <input v-model="address.prefecture" /> <error v-for="(msg, key) in error?.address?.prefecture || []" :key="key" :msg="msg"/> </div> </template>
上記のようにテンプレート内でerror?.address?.prefecture
とすることによって、もしerror
, error.address
, error.address.prefecture
がそれぞれ存在しなかったとしても問題なく実行されるため、無駄にif文で分岐して処理を複雑にする必要はなくなります。
インストール方法
babel7が入っている前提で話をすすめます。babel6以前からのアップデートはbabelupdateを参考にしてください。
まずはyarn (or npm)でプラグインをインストールし、
yarn add @babel/plugin-proposal-optional-chaining
.babelrcでpluginの設定をするだけです、
{ "plugins": ["@babel/plugin-proposal-optional-chaining"] }
Nuxt.jsであればnuxt.config.jsに下記のように記載します
export default { build: { babel: { plugins: ['@babel/plugin-proposal-optional-chaining'] } } }
まとめ
Babel7で新たに入ったOptionalChainingの紹介をさせていただきました。まだProposalの段階なので変更が入る可能性はありますが、より実装にフォーカスしたコーディングができるようになるので、是非導入してみてください!