2 апреля 2017.
Новостная рассылка
Присоединяйтесь к нашему новостному бюллетеню и не пропускайте новости из мира Laravel, анонсы полезных пакетов и советы опытных разработчиков.

Система регистрации пользователей по приглашениям на Laravel

Автор статьи Joe Dixon Joe Dixon | перевод Building a User Invitation System with Laravel | Николенко Виталий

Регистрация пользователей по приглашениям - довольно распространенная задача.

В качестве примера, представьте себе контентый сайт, на котором определённые авторы должны иметь возможность публиковать статьи. Можно конечно же создавать пользователей через админку и потом высылать им пароли. Открытым текстом, почтой, что не есть безопасно.

А можно выслать им инвайт и пускай они сами придумают себе удобный пароль и заполнят персональные данные.

Рассмотрим как это сделать.

Введение

Эту задачу можно реализовать множеством способов. Самый простой метод — создать неактивную учетную запись пользователя, сгенерив для нее некий токен, который будет использоваться в ссылке для активации эккаунта.

Однако, в рамках данного урока, мы рассмотрим решение этой задачи при помощи дополнительной таблицы с приглашениями, где мы будем хранить email и активационный токен. По завершении активации, при помощи этих данных мы создадим эккаунт пользователя.

Будем использовать чистую установку Laravel 5.4, вам необходимо будет сконфигурировать настройки базы данных и почтового сервера.

Миграции

Вместе с дефолтным проектом Laravel в комплекте идет миграция для создания таблицы пользователей.

Для данного примера, мы уберем поля «name» и «password»:

public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->increments('id');
        $table->string('email')->unique();
        $table->rememberToken();
        $table->timestamps();
    });
}

Также нам необходимо создать миграцию для наших инвайтов. В консоли, в папке с проектом выполните команду php artisan make:migration create_invites_table.

Эта команда создаст новый файл в директории database/migrations . В таблице будут поля для первичного ключа, email адреса и уникальный токена

public function up()
{
    Schema::create('invites', function (Blueprint $table) {
        $table->increments('id');
        $table->string('email');
        $table->string('token', 16)->unique();
        $table->timestamps();
    });
}

public function down()
{
    Schema::drop('invites');
}

Теперь выполним миграции при помощи команды php artisan migrate.

Наша база готова

Модели

Нам потребуются модели для управления как членами команды так и приглашениями пользователей.

Как и в случае с миграциями, Laravel имеет модель User из коробки, так что создавать ее не потребуется.

Для инвайтов создадим модель при помощи команды php artisan make:model Invite.

Посмотрите в папку app своего проекта, в ней должен появиться новый файл с нашей моделью.

Все, что осталось сделать с этой моделью — прописать заполняемые поля. Это позволит массово присваивать проперти модели.

protected $fillable = [
    'email', 'token',
];

Роуты

Для этого урока нам потребуется прописать три маршрута (роута):

  • Показать форму приглашения пользователя
  • Обработать отправку формы
  • Принять приглашение

В файле app/routes/web.php добавьте следущее:

Route::get('invite', 'InviteController@invite')->name('invite');
Route::post('invite', 'InviteController@process')->name('process');
// {token}  обязательный параметр, который будет передан в метод контроллера
Route::get('accept/{token}', 'InviteController@accept')->name('accept');

Контроллер

Внимательный читатель, возможно уже заметил, что при описании маршрутов мы ссылались на контроллер InviteController для обработки запросов.

Этот контроллер также можно создать из консоли php artisan make:controller InviteController.

Откройте app/Http/Controllers/InviteController.php и определите следующие методы:

public function invite()
{
    // Покажем форму для ввода email пользователя для приглашения
}

public function process()
{
    // Обработаем отправку формы, пошлем приглашение 
}

public function accept($token)
{
    // Здесь найдем пользователя по токену из URL
}

Вроде ничего не забыли, теперь можно наполнить эти методы, реализовать бизнес-логику.

Бизнес логика

Пройдемся по каждому методу, который создали ранее

invite()

Все просто до безобразия, просто вернем представление с формой, в которую можно ввести email для приглашения.

public function invite()
{
    return view('invite');
}

Создадим файл resources/views/invite.blade.php. Это представление будет содержать нашу форму:

// будем использовать именованный роут на случай смены его  URL, 
<form action="{{ route('invite') }}" method="post">
    {{ csrf_field() }}
    <input type="email" name="email" />
    <button type="submit">Отправить приглашение</button>
</form>

process()

Здесь будет находится львиная доля решения нашей задачи.

Во-первых, нам необходимо уведомить пользователя, что его пригласили зарегистрироваться. Для этого будем использовать mailables Laravel.

Для начала, нам необходимо создать «отправляемый» (mailable) класс. В консоли выполните команду php artisan make:mail InviteCreated.

Эта команда создаст новый класс InviteCreated в директории app/Mail . Откройте его и модифицируйте конструктор, чтобы он принимал модель Invite и присваивал ее в публичную проперти.

use App\Invite;

public function __construct(Invite $invite)
{
    $this->invite = $invite;
}

Для отправки почты, определим метод build следующим образом.

public function build()
{
    return $this->from('you@example.com')
                ->view('emails.invite');
}

Теперь надо создать, упомнятый в методе шаблон, создадим файл resources/views/emails/invite.blade.php с очень простым содержанием:

<p>Привет,</p>

<p>Кто-то пригласил вас зарегистрироваться .</p>

<a href="{{ route('accept', $invite->token) }}">Жамка сюда</a> для активации!

Я слышу, как многие голосят - «Откуда у нас доступ к переменной $invite внутри шаблона!» А вот откуда - Laravel автоматически делает доступными в шаблонах все публичные проперти из отправляемого (mailable) класса.

Вернемся к контроллеру InviteController, нам необходимо сгенерировать уникальный токен, который будет использоваться для идентификации приглашаемого пользователя. Мы будем хранить эту строку в таблице с приглашениями вместе с адресом электронной почты.

use App\Invite;
use App\Mail\InviteCreated;
use Illuminate\Support\Facades\Mail;

...

public function process(Request $request)
{
    // валидация входящих данных

    do {
        //сгенерируем рандомную строку при помощи функции помощника Laravel  `str_random`
        $token = str_random();
    } // Проверим, нет ли уже такого токена, если есть сгенерим заново
    while (Invite::where('token', $token)->first());
    //создадим запись приглашения
    $invite = Invite::create([
        'email' => $request->get('email'),
        'token' => $token
    ]);

    // Отправим инвайт
    Mail::to($request->get('email'))->send(new InviteCreated($invite));

    // сделаем редирект обратно
    return redirect()
        ->back();
}

Отлично! Наше приглашение создано, пользователь уведомлен.

accept()

И, наконец, мы должны описать логику принятия приглашения пользователем. Это будет происходить, когда пользователь перейдет по ссылке из письма.

Обычно запрашивается еще пароль и другие данные для создания пользователя, но в рамках данного примера мы просто проверим существование токена и создадим запись пользователя.

Помните, что токен из урл будет передан в качестве параметра в метод контроллера.

use App\User;
use App\Invite;
use App\Mail\InviteCreated;
use Illuminate\Support\Facades\Mail;

...

public function accept($token)
{
    // Найдем приглашение
    if (!$invite = Invite::where('token', $token)->first()) {
        // если инвайт не существует, можно сделать что-то более элегантное, чем то :)
        abort(404);
    }

    // Создадим пользователя с данными из инвайта
    User::create(['email' => $invite->email]);

    // удалим инвайт, чтобы им нельзя было воспользоваться снова
    $invite->delete();

    // здесь необходимо будет «залогинить» пользователя, сделать редирект в личный кабинет, мы же просто выведем надпись.

    return 'Отлично! Пользователь зарегистрирован!';
}

Проверим, как работает!

Перейдите по адресу формы приглашения ( http://vashdomen.ru/invite), введите email человека, которого хотите пригласить и отправьте форму.

Посомтрите на таблицу с приглашениями в своей БД, там должна быть новая запись с адресом и уникальным токеном. Проверьте ящик, на который было выслано приглашение: должно быть письмо с ссылкой для активации эккаунта.

Перейдите по этой ссылке, вы должны увидеть надпись «Отлично! Пользователь зарегистрирован!» Проверьте БД, запись с приглашением должна исчезнуть и должна появиться запись с созданным пользователем.

Заключение

Отличная работа! Вы успешно создали систему приглашений пользователей.

Хотя это и упрощенный пример, основа заложена приличная.

Расширить функционал довольно легко: после создания эккаунта необходимо будет сделать форму для ввода пароля и других пользовательских данных, также можно добавить функцию аннулирования инвайта и его повторной отправки.




Отправка сообщений в Telegram при помощи каналов уведомлений (Notification Channels)

Используем уведомления для отправки сообщений в Telegram

Как отправить email при возникновении ошибки (исключения) в приложении

Чтобы оперативно исправлять проявляющиеся баги, просто необходимо держать руку на пульсе приложения. Уведомления по email — один из самых эффективных способов.