Загрузка аватарки при помощи Spatie Media Library

По умолчанию форма регистрации в 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, затем редактировать аватар на отдельной странице настроек и т.д. Я оставлю это вам, или, возможно, опишу в потенциальном будущем продолжении этой статьи.

Больше ссылок по теме этого урока:

 

Автор: Povilas Korop
Перевод: Demiurge Ash