Завантаження зображень — стандартна функція для більшості вебзастосунків. У цьому дописі ми розберемося, як реалізувати цей функціонал у Laravel: від базових інструментів до комплексних рішень. Ми розглянемо зміну розміру, оптимізацію та покращення UI, а також покажемо, як пакети від Spatie роблять цей процес простішим та ефективнішим.
Рівень 1: Чистий Laravel та основи завантаження
Почнімо з мінімального прикладу: обробка завантаження за допомогою вбудованих можливостей Laravel, без сторонніх пакетів.
1. Налаштування форми
Спершу створимо форму у Blade-шаблоні:
<form
action="{{ route('upload') }}"
method="POST"
enctype="multipart/form-data"
>
@csrf
<input type="file" name="image">
<button type="submit">Upload</button>
</form>
2. Обробка у контролері
У контролері обробити файл можна так:
public function store(Request $request)
{
$request->validate([
'image' => 'required|image|max:2048', // макс. 2MB
]);
$path = $request->file('image')->store('uploads', 'public');
return back()
->with('success', 'Image uploaded successfully!')
->with('path', $path);
}
Що ми отримали
✅ Робочий процес завантаження
✅ Базову валідацію (тип файлу, розмір)
✅ Збереження у диску public
Чого бракує?
❌ Немає зміни розміру чи маніпуляцій
❌ Відсутня оптимізація продуктивності
❌ Немає попереднього перегляду (previews) в UI
❌ Немає зручного зв’язку зображень із моделями (наприклад, користувачами чи постами)
Рівень 2: Додаємо spatie/image
Коли базове завантаження працює, часто виникає потреба змінити розмір або обрізати фото перед збереженням. У Laravel немає вбудованих інструментів для цього, але пакет spatie/image пропонує елегантний спосіб маніпуляції зображеннями.
Використовуючи цей пакет, ми можемо розширити наш контролер:
public function store(Request $request)
{
$request->validate([
'image' => 'required|image|max:2048',
]);
$uploadedFile = $request->file('image');
// Тимчасово зберігаємо оригінал
$path = $uploadedFile->store('temp');
// Визначаємо фінальний шлях
$finalPath = 'uploads/' . $uploadedFile->hashName();
// Змінюємо розмір та зберігаємо
Image::load(storage_path('app/' . $path))
->width(800)
->save(storage_path('app/public/' . $finalPath));
// Видаляємо тимчасовий оригінал (за бажанням)
Storage::delete($path);
return back()
->with('success', 'Image resized and uploaded!')
->with('path', $finalPath);
}
Інші доступні можливості:
- height(400) — обмеження за висотою
- fit(800, 600) — вписування у задані розміри
- crop(width, height, x, y) — ручне обрізання області
- blur(15) — застосування ефекту розмиття
- greyscale() — перетворення на чорно-біле фото
Повний список методів дивіться у документації spatie/image.
Що ми отримали
✅ Зміна розміру та маніпуляції
✅ Чистий синтаксис ланцюжкових викликів
✅ Підходить для простих завдань
Чого бракує?
❌ Немає оптимізації (розмір файлу може залишатися великим)
❌ Процес усе ще ручний — немає інтеграції з моделями
❌ Відсутні UI-покращення
Рівень 3: Оптимізація розміру файлів із spatie/image-optimizer
Для вебзастосунків критично важливо тримати розмір зображень мінімальним задля продуктивності. Пакет spatie/image-optimizer автоматично стискає зображення за допомогою популярних консольних інструментів (jpegoptim, pngquant, svgo) без помітної втрати якості.
Він безшовно інтегрується з `spatie/image`, тож нам потрібно додати лише один рядок у контролер:
public function store(Request $request)
{
...
// Змінюємо розмір та зберігаємо
Image::load(storage_path('app/' . $path))
->width(800)
->optimize() // Оптимізація перед збереженням
->save(storage_path('app/public/' . $finalPath));
...
}
Що ми отримали
✅ Автоматичне зменшення розміру файлів
✅ Відсутність візуальних втрат якості
✅ Працює з будь-яким флоу обробки фото
Рівень 4: Використання spatie/laravel-medialibrary
Пакет `laravel-medialibrary` виводить роботу з файлами на новий рівень. Він дозволяє прив’язувати завантаження (не лише картинки!) до Eloquent models, автоматично генерувати конверсії та зручно організовувати сховище.
Встановлення
Детальні інструкції можна знайти у документації.
Використання
Після налаштування ми можемо створити модель (наприклад, Post) і просто прикріпити до неї файл:
public function store(Request $request)
{
$request->validate([
'title' => 'required',
'image' => 'required|image|max:2048',
]);
$post = Post::create([
'title' => $request->input('title'),
]);
$post->addMediaFromRequest('image')
->toMediaCollection('featured');
return redirect()->back()
->with('success', 'Post created and image uploaded!');
}
Що ми отримали
✅ Зображення прив'язані до моделей
✅ Автоматичні конверсії (прев'ю, респонсив-дизайн тощо)
✅ Чисте структурування файлів у сховищі
✅ Підтримка колекцій та декількох файлів одночасно
Чого бракує?
❌ Стандартні HTML-форми все ще не дуже зручні (немає drag & drop чи миттєвого прев’ю)
Рівень 5: Media Library Pro для ідеального UI
Коли `laravel-medialibrary` вже працює, **Media Library Pro** робить досвід користувача бездоганним. Це платне доповнення від Spatie, яке надає готові компоненти для Vue, React та Livewire з підтримкою drag & drop, індикаторами прогресу та можливістю змінювати порядок файлів.
💡 Media Library Pro заощадить вам години розробки фронтенду.
Приклад використання у Blade:
<form method="post">
<x-media-library-attachment name="image" rules="mimes:png,jpeg,pdf"/>
<button>Submit</button>
</form>
А у контролері обробка виглядає так:
public function store(Request $request)
{
$request->validate([
'title' => 'required',
'image' => 'required|image|max:2048',
]);
$post = Post::create([
'title' => $request->input('title'),
]);
$post->addFromMediaLibraryRequest('image')
->toMediaCollection('featured');
return redirect()->back()
->with('success', 'Post created and image uploaded!');
}
Результатом буде сучасний функціональний компонент завантаження:

Що ми отримали
✅ Сучасні реактивні UI-компоненти
✅ Глибока інтеграція з моделями
✅ Прев’ю, прогрес-бари та сортування «з коробки»
✅ Підтримка від авторів Media Library
Висновок
Вибір інструментів залежить від потреб вашого проєкту — чи достатньо вам вбудованих засобів Laravel, чи потрібна потужність Media Library Pro. Продукти Spatie пропонують рішення для кожного рівня, допомагаючи створювати чистий, ефективний та масштабований код.