# 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の段階なので変更が入る可能性はありますが、より実装にフォーカスしたコーディングができるようになるので、是非導入してみてください!