Загрузка аватаров с помощью Spatie’s Media Library

Шаг 1: Измените форму регистрации пользователя

Сперва добавим новое поле типа "file" в форму регистрации:

<!-- 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>

Загрузка авартара в Laravel

Шаг 2: Загрузка и сохранение в медиатеке

По-умолчанию форма регистрации обрабатывается в файле 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.php для работы с медиа библиотекой. Для этого нам нужно:

  • Добавить use для двух классов
  • Указать что класс реализует (implements) интерфейс HasMedia
  • Добавить use для трейта HasMediaTrait

// These two come from Media Library
use Spatie\MediaLibrary\HasMedia\HasMediaTrait;
use Spatie\MediaLibrary\HasMedia\HasMedia;

class User extends Authenticatable implements HasMedia
{
  // ...
  use HasMediaTrait;
}

Теперь изменим [email protected] и добавим в него новый функционал:

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;
}

Код выше делает следующее:

  • Проверяет что в запросе есть поле avatar и с помощью Media Library загружает изображение и добавляет его в медиа коллекцию в базе данных
  • Добавлять медиа файлы можно только к существующему пользователю, поэтому мы делаем это только после того как пользователь создан

Вот так файл сохраняется на диске:

Загрузка файлов в Laravel

Внимание: по-умолчанию Laravel сохраняет файлы в папку app/public, так что не забудьте выполнить команду php artisan storage:link чтобы создать символическую ссылку или измените путь в ручную в файле config/filesystems.php.

А вот так это выглядит в базе данных:

Файлы в базе данных в Laravel

Шаг 3: Показать миниатюру аватара в верхней навигации

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

Но во-первых, что, если загруженный файл огромен? Как мы можем изменить размер до 50×50? Здесь Media Library поможет нам снова. Все, что нам нужно сделать, это определить правила изменения размера в app/User.php:

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, и теперь при загрузке изображения, для него автоматически будет создаваться миниатюра в подпапке conversations:

Laravel создание миниатюр изображений

И наконец вот так мы будем выводить аватар в шаблоне:

<!-- 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')

Вот так выглядит финальный результат:

Загруженное изображение

На это все. Конечно, вы можете пойти гораздо глубже, например, показать оригинальное изображение аватара и позволить пользователям самостоятельно изменять размер / обрезать его с помощью какой-либо библиотеки JavaScript, а затем редактировать аватар на отдельной странице настроек и т.д. Я оставлю это вам или, возможно, про это будет рассказанно во второй части статьи.

Перевод статьи Uploading Avatar Images with Spatie’s Media Library.

Опубликовано:

Категории: Статьи