По умолчанию форма регистрации в Laravel содержит только имя, почту и пароль, но часто нужно, чтобы пользователь мог загрузить фотографию или аватар. В этом уроке мы покажем вам простой способ сделать это при помощи пакета Media Library от Spatie.
Шаг 1. Меняем форму регистрации
Давайте добавим поле загрузки файла под именем Avatar к стандартной форме регистрации Laravel:
<!-- resources/views/auth/register.blade.php --> <div class="form-group row"> <label for="avatar" class="col-md-4 col-form-label text-md-right">{{ __('Avatar (optional)') }}</label> <div class="col-md-6"> <input id="avatar" type="file" class="form-control" name="avatar"> </div> </div>
Шаг 2. Загрузка и сохранение при помощи Media Library
По умолчанию регистрация в Laravel обрабатывается в app/Http/Controllers/Auth/RegisterController.php, в частности, в методе create():
/** * Create a new user instance after a valid registration. * * @param array $data * @return \App\User */ protected function create(array $data) { return User::create([ 'name' => $data['name'], 'email' => $data['email'], 'password' => Hash::make($data['password']), ]); }
Здесь мы добавим логику загрузки аватара и сохранение его в базе данных. С этим нам поможет Spatie Media Library. Давайте её установим:
composer require spatie/laravel-medialibrary:^7.0.0
После установки:
php artisan vendor:publish --provider="Spatie\MediaLibrary\MediaLibraryServiceProvider" --tag="migrations"
Делаем миграцию опубликованных таблиц:
php artisan migrate
Это создаст таблицу в базе данных под именем media, которая использует полиморфные отношения для хранения данных.
В нашем случае — мы прикрепляем медиа файлы к app\User.
Теперь давайте подготовим модель app\User.php для работы с Media Library. Вот что нам нужно добавить:
- Два оператора use вне класса
- Класс implements HasMedia
- Один оператор use внутри класса
// Эти два из Media Library use Spatie\MediaLibrary\HasMedia\HasMediaTrait; use Spatie\MediaLibrary\HasMedia\HasMedia; class User extends Authenticatable implements HasMedia { // ... use HasMediaTrait; }
Вернемся к нашему RegisterController и добавим немного кода в метод create():
protected function create(array $data) { $user = User::create([ 'name' => $data['name'], 'email' => $data['email'], 'password' => Hash::make($data['password']), ]); if (isset($data['avatar'])) { $user->addMediaFromRequest('avatar')->toMediaCollection('avatars'); } return $user; }
Что мы здесь сделали:
- Проверка наличия аватара, затем мы используем Media Library для загрузки файла из запроса и добавления его в медиаколлекцию в базе данных;
- Мы можем сделать это только для существующего пользователя, поэтому мы делаем это после того, как пользователь создан, а затем возвращаем конечный результат как объект User.
Вот как хранится файл:
Примечание : по умолчанию Laravel хранит все файлы в storage/app/public, не забудьте запустить команду php artisan storage:link или изменить настройки папок в файле config/filesystems.php.
И как это хранится в базе данных:
Шаг 3. Показ аватара в верхней навигации
Самое простое использование этого аватара — показать его в правом верхнем углу рядом с именем пользователя. Давайте сделаем это.
Но что, если загруженный файл огромен? Как мы можем изменить его размер, скажем, до 50×50? И здесь Media Library снова нам поможет. Все, что нам нужно сделать, это определить правила изменения размера в той же самой модели app\User:
use Spatie\MediaLibrary\Models\Media; class User extends Authenticatable implements HasMedia { // ... all other code public function registerMediaConversions(Media $media = null) { $this->addMediaConversion('thumb') ->width(50) ->height(50); } }
Теперь у нас есть правило под именем thumb которое мы можем использовать для отображения эскиза. При загрузке он будет автоматически сохранен в подкаталог conversions для этого элемента:
Вот так мы показываем аватар:
<!-- resources/views/layouts/app.blade.php --> <a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre> <img src="{{ Auth::user()->getMedia('avatars')->first()->getUrl('thumb') }}"> {{ Auth::user()->name }} <span class="caret"></span> </a>
Да, именно, эта строка нам и нужна:
Auth::user()->getMedia('avatars')->first()->getUrl('thumb')
Мы берем объект модели User, затем получаем все файлы мультимедиа из коллекции avatars, затем берем первый и получаем URL на изображение сконвертированное как thumb.
Окончательно всё выглядит так:
Вот и все. Конечно, вы можете пойти дальше и, например, показать оригинальный аватар и позволить пользователям самим изменять его размер или обрезать с помощью некой библиотеки JavaScript, затем редактировать аватар на отдельной странице настроек и т.д. Я оставлю это вам, или, возможно, опишу в потенциальном будущем продолжении этой статьи.
Больше ссылок по теме этого урока:
- Документация Spatie Media Library
- Eloquent Отношения: Полное Руководство по Полиморфным Отношениям
- Загрузка файлов в Laravel: полное руководство
Автор: Povilas Korop
Перевод: Алексей Широков
Наш Телеграм-канал — следите за новостями о Laravel.