前回で披露したコントローラー中でのルールの共有のメソッドrules()では、新規レコード作成と既存レコードの編集における入力項目の違いを、$actionの引数をswitchで分岐して対応しました。今回は、sometimesを使用してそれらの必要性をなくします。

sometimesは、入力項目があるときのみに、それ以降のルールを適応するルールです。tinkerを使ってテストしてみましょう。

通常は、

>>> $input = [];
=> []
>>> $rules = ['email' => 'required|email'];
=> [
     "email" => "required|email",
   ]
>>> validator($input, $rules)->errors()->all();
=> [
     "必ず指定してください",
   ]

とエラーとなるところ、sometimesを使用すると、

>>> $input = [];
=> []
>>> $rules = ['email' => 'sometimes|required|email'];
=> [
     "email" => "sometimes|required|email",
   ]
>>> validator($input, $rules)->errors()->all();
=> []
>>> 

とemailの項目が入力にないのにエラーとはなりません。

これを利用して前回のrules()の定義を書き変えてみます。

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Validation\Rule;

use App\User;

class UserController extends Controller
{
    public function rule(User $user = null)
   {
        // 共有するルール kana, mailcode, phone_with_dashはカスタムバリデーター
        $rules = [
            'name'        => 'required',
            'name_kana'   => 'required|kana',
            'mailcode'    => 'required|mailcode',
            'prefecture'  => 'required',
            'city'        => 'required',
            'address1'    => 'required',
            'phone'       => 'required|phone_with_dash',
            'password'    => 'sometimes|required|min:8|max:20|confirmed',
            'email'       => [
                    'required',
                    'email',
                    Rule::unique('users')->ignore(optional($user)->id), //重複がないかチェック
                ]
        ];

        return [
            // rules
            $rules,
            // messages
            [
                'password.min' => '8から20文字長でお願いします',
                'password.max' => '8から20文字長でお願いします'
            ]
            // attributes
        ];
    }
...
    public function store(Request $request)
    {
        $request->validate(...$this->rules());
        ...
    }
...
    public function update(Request $request, User $user)
    {
        $request->validate(...$this->rules($user));
        ...
    }
...

前回と変わったのは、関数の引数の$actionとその値によるswitchによる分岐がなくなっています。新規作成時しか必要でない、passwordの項目に、sometimesを使用して、その項目がないときはルールを適用しないようにしています。また、emailの重複のチェックにおいては、以下のようにヘルパーのoptional()を使用して、新規には存在しない$userの値でundefinedのエラーが出ないようにしています。

Rule::unique('users')->ignore(optional($user)->id)

最後に、sometimes|requiredは以下のようにfilledに置き換えることも可能です。filledに関してはこちらも参考にしてください。

'password' => 'filled|min:8|max:20|confirmed'

By khino