Довольно часто, особенно в интернет-магазинах, вы можете увидеть страницу с формами входа или регистрации перед завершением покупки. Но в Laravel эти два маршрута ведут на отдельные страницы входа и регистрации. Как их объединить и избежать конфликта?
Обратите внимание: в конце этой статьи вы найдете ссылку на Github с простым проектом оформления заказа.
Это страница перед покупкой, к которой мы стремимся:
На первый взгляд, это довольно просто — скопировать/вставить весь код из /resources/views/auth/login.blade.php и /resources/views/auth/register.blade.php в один общий, скажем, /resources/views/checkout.blade.php. Так и есть, но это еще не всё.
Проблема возникнет из-за одинаковых имен полей.
Форма входа:
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>
Форма регистрации:
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="register_email" value="{{ old('email') }}" required autocomplete="email">
Видите разницу? Я тоже не вижу. За исключением автофокуса, который, в нашем случае, не имеет значения.
Вы можете подумать, что всё нормально, так как они отправляются данные на разные адреса и выполняют разные действия. Но, в случае неудачной проверки, вы получаете ошибки в обеих формах, а не в одной. Например, в случае неверных учетных данных при входе в систему, вы увидите это:
Как этого избежать?
Шаг 1. Переименуйте поля в одной из форм.
В этом примере мы переименуем поля в регистрации, добавив к ним префикс «register_»:
<input id="register_name" type="text" class="form-control @error('register_name') is-invalid @enderror" name="register_name" value="{{ old('register_name') }}" required autocomplete="name" autofocus> @error('register_name') <span class="invalid-feedback" role="alert"> <strong>{{ $message }}</strong> </span> @enderror ... <input id="register_email" type="email" class="form-control @error('register_email') is-invalid @enderror" name="register_email" value="{{ old('register_email') }}" required autocomplete="email"> @error('register_email') <span class="invalid-feedback" role="alert"> <strong>{{ $message }}</strong> </span> @enderror ... <input id="register_password" type="password" class="form-control @error('register_password') is-invalid @enderror" name="register_password" required autocomplete="new-password"> @error('register_password') <span class="invalid-feedback" role="alert"> <strong>{{ $message }}</strong> </span> @enderror ... <input id="password-confirm" type="password" class="form-control" name="register_password_confirmation" required autocomplete="new-password">
Шаг 2. Переопределите валидатор в RegisterController.
Исходный метод validator() из
/Http/Controllers/Auth/RegisterController.php, прямо из фреймворка:
protected function validator(array $data) { return Validator::make($data, [ 'name' => ['required', 'string', 'max:255'], 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], 'password' => ['required', 'string', 'min:8', 'confirmed'], ]); }
Итак, нам нужно переопределить этот валидатор своим собственным, добавив в него некоторые правила. Фактически нам просто нужно использовать переименованные поля из шага 1, а затем правильно назначить их имена. Вот код:
protected function validator(array $data) { $validator = Validator::make($data, [ 'register_name' => ['required', 'string', 'max:255'], 'register_email' => ['required', 'string', 'email', 'max:255', 'unique:users,email'], 'register_password' => ['required', 'string', 'min:8', 'confirmed'], ]); $validator->setAttributeNames([ 'register_name' => 'name', 'register_email' => 'email', 'register_password' => 'password', ]); return $validator; }
Как видите, теперь мы используем поля register_xxx вместо просто xxx, но нам также нужно убедиться, что они возвращают ошибки с их «оригинальными» именами, поэтому для этого мы используем не очень известный метод setAttributeNames(). Это официально не упоминается в документации, но вы можете увидеть пример его использования в этой теме на StackOverflow.
Вот и всё! Теперь у нас есть две отдельные формы на странице оформления заказа.
Бонус: Интернет-магазин Checkout Demo
В рамках этой статьи мы фактически создали типичный мини-проект процесса оформления заказа, который вы можете увидеть на Github. Домашняя страница содержит список продуктов, вы можете купить любой из них, а в сессии содержится ваша «корзина», которую вы можете оформить в любое время, нажав «Оформить заказ» наверху.
Мы не реализовали фактический процесс оплаты, но, думаю, это всё ещё полезный пример для Laravel юниоров. Наслаждайтесь!
Автор: Povilas Korop
Перевод: Алексей Широков
Наш Телеграм-канал — следите за новостями о Laravel.