С использованием аутентификации из коробки
Для тестирования кода использовался Laravel 5.5, но я думаю подойдут и версии 5.3 или 5.4.
Так как здесь мы используем аутентификацию из коробки, то ее нужно сначала установить, делается это с помощью команды:
php artisan make:auth
В результате чего вы получите, готовую к использованию, систему регистрации и авторизации пользователей, а также набор необходимых контроллеров и видов для возможной ее кастомизации.
В данном примере мы это и сделаем, кастомизируем предлагаемый функционал регистрации и авторизации, и добавим в него возможность подтверждения регистрации по e-mail. Для этого, как было сказано вначале, нам нужно добавить 2 дополнительных поля в таблицу users (verified и token). У нас уже есть стандартный файл миграции create_users_table.php, можно добавить 2 новых поля прямо в него, но у кого-то миграция уже может быть проведена и таблицы в БД уже созданы, поэтому удобнее было бы просто добавить 2 новых поля к существующей таблице. Так мы и поступим.
Для добавления двух новых полей к таблице нам нужно создать дополнительный файл миграции, который это делает. Для его создания потребуется следующая команда:
php artisan make:migration add_verified_token_fields_to_users_table —table=users
После этого в папке migrations появится новый файл. Откроем его и в метод up() добавим следующее содержимое:
Schema::table('users', function (Blueprint $table) {
$table->boolean('verified')->default(false);
$table->string('token')->nullable();
});
Теперь осталось провести миграцию командой:
php artisan migrate
С БД закончили, теперь переходим к добавлению нового функционала.
По традиции начнем с маршрутов. Откроем файл web.php и добавим в него маршрут, по которому будет осуществляться сверка ключа (token) из пользовательской ссылки и ключа в БД.
Route::get('register/confirm/{token}', 'Auth\RegisterController@confirmEmail');
Как видим за данную проверку должен отвечать метод confirmEmail() контроллера Auth\RegisterController. Сам контроллер у нас уже есть, поэтому откроем его и добавим необходимый метод. Выглядеть он должен следующим образом:
public function confirmEmail(Request $request, $token)
{
User::whereToken($token)->firstOrFail()->confirmEmail();
$request->session()->flash('message', 'Учетная запись подтверждена. Войдите под своим именем.');
return redirect('login');
}
Продолжим работу с контроллером. В заголовке добавим следующие строчки:
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use App\Mail\UserRegistered;
В последней строчке UserRegistered – это mailable-класс, который будет отвечать за отправку писем. Мы создадим его позже, потому что в контроллер нам нужно добавить еще один метод. Это метод register(), отвечающий за сам процесс регистрации. Выглядеть он должен следующим образом:
public function register(Request $request)
{
$this->validator($request->all())->validate();
$user = $this->create($request->all());
Mail::to($user)->send(new UserRegistered($user));
$request->session()->flash('message', 'На ваш адрес было выслано письмо с подтверждением регистрации.');
return back();
}
Здесь мы создаем новую запись в таблице users и отправляем письмо-подтверждение регистрации. Важный момент в том, что при создании новой записи туда еще нужно добавить случайное значение в поле token. Делается это с помощью метода boot() модели User. Откроем модель и добавим туда этот метод.
public static function boot()
{
parent::boot();
static::creating(function ($user) {
$user->token = str_random(30);
});
}
Также в модель мы должны добавить метод, который будет обнулять ключ и устанавливать значение поля verified равным true, в случае, если пользователь успешно подтвердит свой e-mail адрес.
public function confirmEmail()
{
$this->verified = true;
$this->token = null;
$this->save();
}
С моделью закончили. Теперь нам нужно создать mailable-класс отправки письма UserRegistered, который мы используем в контроллере Auth\RegisterController. Для этого воспользуемся следующей командой:
php artisan make:mail UserRegistered
После чего в директории проекта появится новая папка Mail, а в ней файл UserRegistered.php, с mailable-классом. Для нашего проекта содержимое класса UserRegistered будет следующим:
use Queueable, SerializesModels;
public $user;
public function __construct(User $user)
{
$this->user = $user;
}
public function build()
{
return $this->to($this->user->email)
->view('auth.emails.confirm');
}
В методе build() мы используем вид confirm.blade.php (папка /resources/views/auth/emails), в котором содержится структура письма. Структура может быть такая:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Активация регистрации нового ползователя</title>
</head>
<body>
<h1>Спасибо за регистрацию, {{$user->name}}!</h1>
<p>
Перейдите <a href='{{ url("register/confirm/{$user->token}") }}'>по ссылке </a>чтобы завершить регистрацию!
</p>
</body>
</html>
На этапе разработки для получения писем можно воспользоваться файлом laravel.log. Для этого в файле .env в строчке MAIL_DRIVER нужно указать log.
На данный момент мы сделали все, чтобы пользователь мог зарегистрироваться и пройти проверку подлинности, указанного во время регистрации почтового ящика. Но остался важный момент – изменить функционал предустановленной авторизации, для того чтобы на сайт могли входить только пользователи, прошедшие e-mail-проверку, то есть те пользователи, у которых поле verified равно true.
Для этого откроем уже существующий Auth\LoginController. В заголовок класса добавим строчку:
use Illuminate\Http\Request;
И добавим 2 новых метода: attemptLogin() и credentials(). Второй метод вспомогательный, то есть используется в первом. Оба метода выполняют аутентификацию пользователя, если поле verified у пользователя равно true.
protected function attemptLogin(Request $request)
{
return $this->guard()->attempt(
$this->credentials($request), $request->filled('remember')
);
}
protected function credentials(Request $request)
{
return array_add($request->only($this->username(), 'password'), 'verified', true);
}
Основную часть работы мы сделали, осталось добавить в виды register.blade.php и login.blade.php вывод сообщений о том, что письмо было выслано, и что учетная запись была подтверждена.
Код отвечающий за вывод сообщения одинаковый для обоих видов:
@if (session()->has('message'))
<div class="alert alert-info">{{ session('message') }}</div>
@endif
После этого страница регистрации будет выглядеть так:
Страница аутентификации так: