Мини-блог на Laravel, часть 8. Регистрация и аутентификация пользователей на сайте
25.09.2020
Теги: Laravel • MySQL • PHP • Web-разработка • Аутентификация • БазаДанных • Блог • Пользователь • Практика • Форма • Фреймворк
В Laravel сделать аутентификацию очень просто — почти всё готово из коробки. Мы уже установили ранее пакет laravel/ui
, чтобы использовать в шаблонах фреймворк bootstrap. Для создания заготовок всех необходимых для аутентификации контроллеров, шаблонов и роутов нужно выполнить artisan-команду.
> php artisan ui:auth > npm install && npm run dev
Будут созданы контроллеры:
RegisterController
— обеспечивает регистрацию пользователейLoginController
— обеспечивает аутентификацию пользователейForgotPasswordController
— отправляет письмо на сброс пароляResetPasswordController
— содержит логику для сброса паролей
Будут созданы шаблоны:
auth.register
— форма регистрации пользователейauth.login
— форма аутентификации пользователейauth.passwords.email
— форма для ввода адреса почты (восстановление пароля)auth.passwords.reset
— форма для ввода нового пароля (восстановление пароля)
Будут добавлены маршруты:
Auth::routes(); Route::get('/home', 'HomeController@index')->name('home');
Вызов Auth::routes()
добавляет сразу около дюжины маршрутов, посмотреть эти маршруты можно в классе Laravel\Ui\AuthRouteMethods
.
Кроме того, будет добавлен контроллер HomeController
, отвечающий за показ страницы /home
. После регистрации и аутентификации пользователи перенаправляются на эту страницу. Нам этот контроллер не нужен, так что можно его удалить. Также можно удалить шаблоны home.blade.php
и app.blade.php
— но пока не будем этого делать, нам нужно кое-что забрать оттуда.
Сейчас пользователи уже могут регистрироваться и аутентифицироваться. Если открыть в браузере страницу /register
, то будет показана форма регистрации нового пользователя.
Но не хватает перевода на русский язык. Чтобы получить языковые файлы, установим пакет
> composer require laravel-lang/lang:~7.0
После этого нужно скопировать директорию vendor/laravel-lang/lang/src/ru
и файл vendor/laravel-lang/lang/json/ru.json
в директорию resources/lang
. И смотрим на форму регистрации пользователей еще раз.
Теперь посмотрим, что находится в layout-шаблоне app.blade.php
. Нас интересует следующий фрагмент кода:
<!-- Right Side Of Navbar --> <ul class="navbar-nav ml-auto"> <!-- Authentication Links --> @guest <li class="nav-item"> <a class="nav-link" href="{{ route('login') }}">{{ __('Login') }}</a> </li> @if (Route::has('register')) <li class="nav-item"> <a class="nav-link" href="{{ route('register') }}">{{ __('Register') }}</a> </li> @endif @else <li class="nav-item dropdown"> <a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre> {{ Auth::user()->name }} </a> <div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown"> <a class="dropdown-item" href="{{ route('logout') }}" onclick="event.preventDefault(); document.getElementById('logout-form').submit();"> {{ __('Logout') }} </a> <form id="logout-form" action="{{ route('logout') }}" method="POST" class="d-none"> @csrf </form> </div> </li> @endguest </ul>
Скопируем его и вставим в наш layout-шаблон site.blade.php
:
<!doctype html> <html lang="ru"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>{{ $title ?? 'Веб-разработка' }}</title> <link rel="shortcat icon" type="image/png" href="{{ asset('favicon.png') }}"/> <link rel="stylesheet" href="{{ asset('css/app.css') }}"> <script src="{{ asset('js/app.js') }}"></script> </head> <body> <div class="container"> <nav class="navbar navbar-expand-lg navbar-dark bg-dark"> <a class="navbar-brand" href="{{ route('blog.index') }}">Веб-разработка</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <!-- ссылки слева --> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav mr-auto"> <li class="nav-item"> <a class="nav-link" href="#">Авторы</a> </li> <li class="nav-item"> <a class="nav-link" href="{{ route('post.create') }}">Создать</a> </li> <li class="nav-item"> <a class="nav-link" href="#">Контакты</a> </li> </ul> <!-- форма поиска --> <form class="form-inline my-2 my-lg-0" action="{{ route('post.search') }}"> <input class="form-control mr-sm-2" type="search" name="search" placeholder="Найти пост..." aria-label="Поиск"> <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Поиск</button> </form> <!-- ссылки справа --> <ul class="navbar-nav ml-auto"> @guest <li class="nav-item"> <!-- ссылка для входа --> <a class="nav-link" href="{{ route('login') }}">{{ __('Login') }}</a> </li> @if (Route::has('register')) <li class="nav-item"> <!-- ссылка для регистрации --> <a class="nav-link" href="{{ route('register') }}">{{ __('Register') }}</a> </li> @endif @else <li class="nav-item"> <a class="nav-link" href="{{ route('logout') }}" onclick="event.preventDefault(); document.getElementById('logout-form').submit();"> {{ __('Logout') }} <!-- ссылка выхода --> </a> <form id="logout-form" action="{{ route('logout') }}" method="POST" class="d-none"> @csrf </form> </li> @endguest </ul> </div> </nav> @if ($message = Session::get('success')) <div class="alert alert-success alert-dismissible mt-4" role="alert"> <button type="button" class="close" data-dismiss="alert" aria-label="Закрыть"> <span aria-hidden="true">×</span> </button> {{ $message }} </div> @endif @if ($errors->any()) <div class="alert alert-danger alert-dismissible mt-4" role="alert"> <button type="button" class="close" data-dismiss="alert" aria-label="Закрыть"> <span aria-hidden="true">×</span> </button> <ul class="mb-0"> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif @yield('content') </div> </body> </html>
Теперь посмотрим на шаблон home.blade.php
:
@extends('layouts.app') @section('content') <div class="container"> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card"> <div class="card-header">{{ __('Dashboard') }}</div> <div class="card-body"> @if (session('status')) <div class="alert alert-success" role="alert"> {{ session('status') }} </div> @endif {{ __('You are logged in!') }} </div> </div> </div> </div> </div> @endsection
Здесь должно показываться flash-сообщение, но flash-переменная не установлена, так что давайте это исправим.
class RegisterController extends Controller { /* ... */ /** * Сразу после регистрации выполняем редирект и устанавливаем flash-сообщение */ protected function registered(Request $request, $user) { return redirect($this->redirectTo) ->with('status', trans('auth.success')); } }
class LoginController extends Controller { /* ... */ /** * Сразу после входа выполняем редирект и устанавливаем flash-сообщение */ protected function authenticated(Request $request, $user) { return redirect($this->redirectTo) ->with('status', __('You are logged in!')); } /** * Сразу после выхода выполняем редирект и устанавливаем flash-сообщение */ protected function loggedOut(Request $request) { return redirect($this->redirectTo) ->with('status', trans('auth.loggedout')); } }
Для сообщения «You are logged in!» нашелся подходящий перевод в файле ru.json
, а вот сообщения об успешной регистрации и выходе из системы найти не удалось, так что добавим ключи regsuccess
и loggedout
в файл resources/lang/ru/auth.php
.
return [ 'failed' => 'Неверное имя пользователя или пароль.', 'throttle' => 'Слишком много попыток входа. Пожалуйста, попробуйте еще раз через :seconds секунд.', 'regsuccess' => 'Регистрация прошла успешно!', 'loggedout' => 'Вы вышли из системы!', ];
Мы все flash-сообщения показываем в layout-шаблоне, так что изменим в методах registered()
, authenticated()
и loggedout()
ключ status
на ключ success
. И изменим значение переменной redirectTo
, чтобы после регистрации, входа и выхода пользователи перенаправлялись на главную страницу.
class RegisterController extends Controller { /** * Сразу после регистрации выполняем редирект на главную страницу сайта */ protected $redirectTo = '/'; /* ... */ /** * Сразу после регистрации выполняем редирект и устанавливаем flash-сообщение */ protected function registered(Request $request, $user) { return redirect($this->redirectTo) ->with('success', trans('auth.success')); } }
class LoginController extends Controller { /** * Куда выполнять редирект после входа в систему и после выхода из системы */ protected $redirectTo = '/'; /* ... */ /** * Сразу после входа выполняем редирект и устанавливаем flash-сообщение */ protected function authenticated(Request $request, $user) { return redirect($this->redirectTo) ->with('success', __('You are logged in!')); } /** * Сразу после выхода выполняем редирект и устанавливаем flash-сообщение */ protected function loggedOut(Request $request) { return redirect($this->redirectTo) ->with('success', trans('auth.loggedout')); } }
И нам еще осталось стилизовать страницы регистрации, аутентификации и восстановления пароля, чтобы шапка сайта была как на всех прочих страницах. Для этого достаточно изменить директиву @extends()
и убрать div
с css-классом container
(контейнер у нас уже есть в layout-шаблоне).
@extends('layouts.site') @section('content') <div class="row justify-content-center"> <div class="col-md-8"> <!-- здесь форма регистрации --> </div> </div> @endsection
@extends('layouts.site') @section('content') <div class="row justify-content-center"> <div class="col-md-8"> <!-- здесь форма аутентификации --> </div> </div> @endsection
@extends('layouts.site') @section('content') <div class="row justify-content-center"> <div class="col-md-8"> <!-- здесь форма ввода адреса почты (восстановление пароля) --> </div> </div> @endsection
@extends('layouts.site') @section('content') <div class="row justify-content-center"> <div class="col-md-8"> <!-- здесь форма ввода нового пароля (восстановление пароля) --> </div> </div> @endsection
Теперь можно удалить контроллер HomeController
, layout-шаблон app.blade.php
и шаблон home.blade.php
.
- Блог на Laravel 7, часть 3. Checkbox «Запомнить меня» и подтверждение адреса почты
- Блог на Laravel 7, часть 2. Регистрация и аутентификация, восстановление пароля
- Мини-блог на Laravel, часть 9. Защита маршрутов создания, редактирования и удаления
- Блог на Laravel 7, часть 17. Временная зона для пользователей, деплой на хостинг TimeWeb
- Блог на Laravel 7, часть 13. Загрузка и ресайз изображений для категорий и постов блога
- Блог на Laravel 7, часть 11. Панель управления — назначение ролей и прав для пользователей
- Блог на Laravel 7, часть 10. Личный кабинет — CRUD-операции над постами и комментариями
Поиск: Laravel • Web-разработка • Блог • Практика • Форма • Фреймворк • Аутентификация • База данных • MySQL • PHP • Пользователь