Использование нескольких пользовательских моделей в Laravel Jetstream

multiple user models with laravel jetstream

Когда я создавал свой новый проект, то начал с установки каркаса аутентификации Laravel Jetstream. Но мне нужно было несколько моделей пользователей: Developer — для разработчиков, и Recruiter — для рекрутеров. Причем каждая из моделей должна иметь свои собственные отношения, а отношения из других моделей (например, Skill и Stack) должны ссылаться на эти конкретные модели, а не на общую модель User. А Jetstream предполагает существование всего одной пользовательской модели — User. Что же делать?

Но, к моему счастью, Калеб Порцио создал для этого отличный пакет: Parental. Давайте разберём, что он умеет и как им пользоваться.

Миграции

Добавьте в таблицу type строковое поле users.

$table->string('type');

Модели

Создайте нужные вам модели и примените к ним трейт HasParent:

class Developer extends User
{
    use HasParent;
  
    // developer отношения...
}

class Recruiter extends User
{
    use HasParent;
  
    // recruiter отношения...
}

Затем внесите следующие изменения в модель User:

class User extends Authenticable
{
    use HasChildren;

    protected $childTypes = [
        'developer' => Developer::class,
        'recruiter' => Recruiter::class,
    ];
  
    public function isDeveloper(): bool
    {
        return $this->type === 'developer';
    }

    public function isRecruiter(): bool
    {
        return $this->type === 'recruiter';
    }
}

Трейты добавляют поддержку parental и хелперы для таких проверок как auth()->user()->isDeveloper().

Хелперы

Вы также можете создать глобальный хелпер. Лично я сделал метод developer() для получения текущего разработчика. И такой же для рекрутера — recruiter(). Если текущий пользователь не является разработчиком, то developer() вернет null. Это означает, что мы можем делать такие вещи, как:

Вы также можете использовать хелперы в своем коде:

abort_unless(recruiter(), 403);

Чтобы добавить эти хелперы, создайте файл src/helpers.php:

function developer(): ?Developer
{
    $user = auth()->user();

    if ($user instanceof Developer) {
        return $user;
    }

    return null;
}

function recruiter(): ?Recruiter
{
    $user = auth()->user();

    if ($user instanceof Recruiter) {
        return $user;
    }

    return null;
}

И добавьте путь к нему в раздел autoload.files файла composer.json.

"autoload": {
    "psr-4": {...},
    "files": [
      	"src/helpers.php"
    ],
}

Регистрация

Возможно вы также захотите кастомизировать страницу регистрации. Например принимать пользовательский тип в <select> и создавать команду только в том случае, если пользователь относится к определенному типу. В этом случае вы должны провести валидацию значения и сохранить его через класс App\Actions\Fortify\CreateNewUser:

'type' => ['required', Rule::in(['developer', 'recruiter'])],

Заключение

Вот и все. Parental автоматически, при вызове auth()->user(), возвращает правильный класс, и вы можете добавлять отношения к вашим конкретным пользовательским моделям.

Автор: Samuel Štancl
Перевод: Алексей Широков

Наш Телеграм-канал — следите за новостями о Laravel.