Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти
Інше
Події Про нас
Новини 24 липня 2026

Практичний посібник з обробки зображень в Laravel

Laravel 13.20 представив власний компонент обробки зображень через новий Illuminate\Image у Pull Request #59276. До цього релізу для зміни розміру аватара або конвертації завантаженого файлу в WebP доводилося використовувати сторонні пакети.

Тепер фреймворк постачається з fluent, immutable API, який покриває типові сценарії: зміну розміру, обрізку, конвертацію форматів, контроль якості, застосування ефектів та збереження результату на будь-якому файловому диску.

Налаштування

Драйвери GD та Imagick базуються на Intervention Image v4, який є рекомендованою, а не обов'язковою залежністю. Встановіть його командою:

composer require intervention/image:^4.0

За замовчуванням Laravel використовує драйвер GD. Якщо на вашому сервері встановлено розширення Imagick, ви можете зробити його драйвером за замовчуванням через конфігураційне значення images.default або перемикати драйвери для кожного зображення окремо:

$image->usingImagick()->toBytes();
// Або за назвою:
$image->using('imagick')->toBytes();

Якщо ви викликаєте драйвер без встановленого Intervention Image, Laravel викидає ImageException із точною інструкцією, що потрібно встановити.

Створення екземпляра Image

Зображення можуть надходити звідки завгодно: із завантаження, сховища, локального шляху, URL або сирих байтів. Новий метод Request::image() є найзручнішою точкою входу для завантажень:

$image = $request->image('avatar'); // ?Illuminate\Image\Image

Він повертає null, коли поле відсутнє або не є завантаженим файлом, тому спочатку валідуйте завантаження як зазвичай.

Фасад Image та Storage покривають усі інші джерела:

use Illuminate\Support\Facades\Image;
use Illuminate\Support\Facades\Storage;

$image = Image::fromPath('/path/to/photo.jpg');
$image = Image::fromUrl('https://example.com/photo.jpg');
$image = Image::fromStorage('uploads/photo.jpg', 's3');
$image = Image::fromBytes($contents);
$image = Image::fromBase64($encoded);

// Еквівалент fromStorage():
$image = Storage::disk('s3')->image('uploads/photo.jpg');

Як працює конвеєр обробки

Кожна трансформація повертає новий екземпляр Image, і нічого не обробляється, доки ви не запитаєте вивід (store(), toBytes(), width() тощо). Це має приємний практичний наслідок: ви можете створити базове зображення і розгалузити кілька варіантів без того, щоб трансформації одного варіанта просочилися в інший:

$photo = Image::fromStorage('uploads/photo.jpg')->orient();

$thumbnail = $photo->cover(300, 300)->quality(60)->toWebp();
$display = $photo->scale(width: 1600)->quality(80)->toWebp();

$thumbnail->storeAs('photos', 'photo-thumb.webp', disk: 's3');
$display->storeAs('photos', 'photo-display.webp', disk: 's3');

Виклик orient() автоматично повертає зображення на основі його EXIF-даних - це варто робити першим для будь-якої фотографії з камери телефону.

Зміна розміру: cover, contain, scale, resize та crop

API пропонує п'ять способів змінити розміри, і вибір правильного має значення:

  • cover($width, $height) змінює розмір і обрізає для заповнення точних розмірів. Використовуйте для аватарів і мініатюр, де потрібен фіксований розмір без спотворень.
  • contain($width, $height, $background) вміщує повне зображення всередині розмірів, заповнюючи простір необов'язковим кольором фону.
  • scale($width, $height) змінює розмір пропорційно і ніколи не збільшує - внутрішньо відповідає scaleDown() в Intervention. Будь-який розмір можна пропустити. Це безпечний вибір для "зменшити максимум до X пікселів завширшки".
  • resize($width, $height) примусово встановлює точні розміри і може спотворити зображення.
  • crop($width, $height, $x, $y) вирізає регіон з оригіналу за заданим зміщенням.
$image->cover(512, 512);          // точний квадрат, обрізаний під розмір
$image->contain(800, 600, '#fff'); // з білими полями
$image->scale(width: 1200);        // пропорційно, без збільшення
$image->crop(400, 300, x: 100, y: 50);

Ефекти та коригування

Набір методів коригування завершує трансформаційний набір:

$image
    ->rotate(90)          // за годинниковою, необов'язковий фон для відкритих кутів
    ->blur(10)            // 0-100, за замовчуванням 5
    ->sharpen(15)         // 0-100, за замовчуванням 10
    ->grayscale()
    ->flip()              // вертикально; також працює flipVertically()
    ->flop();             // горизонтально; аліас flipHorizontally()

Формати, якість та optimize()

Конвертація форматів проста, використовуючи методи toWebp(), toJpg(), toPng(), toGif(), toAvif() та toBmp(). Якість (1-100) застосовується до форматів із втратами - WebP, JPEG та AVIF:

$image->toWebp()->quality(80);

Метод optimize() - це ярлик, який конвертує в WebP з якістю 70 за замовчуванням і приймає формат та якість, якщо потрібні інші значення:

$image->optimize();             // WebP з якістю 70
$image->optimize('avif', 60);   // AVIF з якістю 60

Драйвери GD та Imagick приймають на вхід зображення JPEG, PNG, GIF, BMP та WebP.

Збереження та отримання результату

Методи збереження віддзеркалюють API UploadedFile у Laravel, тому оброблені зображення використовують налаштований диск:

$path = $image->store('avatars');                       // випадкова хешована назва
$path = $image->storeAs('avatars', 'user-1.webp');      // явна назва
$path = $image->storePublicly('avatars', disk: 's3');   // публічна видимість

Хешована назва файлу автоматично отримує правильне розширення для вихідного формату - збережіть JPEG-завантаження після виклику toWebp(), і файл буде названий *.webp.

Коли вам потрібні дані замість файлу, також можна використати toBytes(), toBase64() або toDataUri().

Методи інспекції запускають конвеєр і звітують про оброблений результат:

$image->width();       // int
$image->height();      // int
$image->dimensions();  // [width, height]
$image->mimeType();    // наприклад "image/webp"
$image->extension();   // наприклад "webp"

Data URI зручний для вбудовування малих прев'ю безпосередньо в HTML або електронні листи:

$avatar = Storage::image("avatars/{$user->avatar}")
    ->cover(64, 64)
    ->toDataUri();

Збираємо все разом: завантаження аватарів

Ось повний процес, який ви могли б використати в методі контролера, що орієнтує завантаження, обрізає до розміру 512×512, конвертує в WebP і публічно зберігає на S3:

public function update(Request $request)
{
    $request->validate([
        'avatar' => ['required', 'image', 'max:5120'],
    ]);

    $path = $request->image('avatar')
        ->orient()
        ->cover(512, 512)
        ->optimize()
        ->storePublicly('avatars', disk: 's3');

    $request->user()->update(['avatar_path' => $path]);

    return back();
}

Ви також можете згенерувати набір адаптивних варіантів у невеликому циклі:

foreach ([480, 960, 1440] as $width) {
    Image::fromStorage($path, 's3')
        ->scale(width: $width)
        ->toWebp()
        ->storeAs('photos/variants', "{$name}-{$width}w.webp", disk: 's3');
}

Оскільки scale() ніколи не збільшує, оригінал шириною 900 пікселів, переданий через ітерацію 1440, залишається 900 пікселів замість розтягування.

Умовні трансформації

Клас Image використовує трейт Conditionable, тому when() та unless() працюють так само, як і в інших місцях Laravel:

$image = $request->image('photo')
    ->when($request->boolean('grayscale'), fn ($image) => $image->grayscale())
    ->scale(width: 1200)
    ->optimize();

Налаштування та розширення

Окрім заміни драйверів, є дві точки розширення. Метод Image::extend() реєструє повністю користувацький драйвер, слідуючи тому самому шаблону, що й інші менеджери Laravel. Метод Image::transformUsing() можна використовувати для перевизначення того, як обробляється окрема трансформація для заданого драйвера:

use Illuminate\Image\Transformations\Blur;
use Illuminate\Support\Facades\Image;

Image::transformUsing('gd', Blur::class, function ($image, Blur $blur) {
    return $image->blur(min(100, $blur->amount * 2));
});

Ви також можете написати власну трансформацію, реалізувавши контракт Illuminate\Contracts\Image\Transformation і передавши екземпляр в $image->transform().

Кілька важливих моментів

  • Зображення не можна серіалізувати. Спроба надіслати екземпляр Image до завдання черги викидає ImageException. Замість цього спочатку збережіть зображення і передайте шлях до завдання.
  • Обробка ледача і кешована. Конвеєр запускається один раз при першому виведенні; наступні виклики width(), toBytes() тощо повторно використовують оброблений результат.
  • Помилки викидають ImageException, включно з непідтримуваними вхідними форматами та файлами, які неможливо декодувати, тому try/catch навколо обробки дає вам один тип винятку для обробки.

Функціональність з'явилася в Laravel 13.20, і ви можете переглянути повну реалізацію в Pull Request #59276 на GitHub.

7

Коментарі

Увійдіть, щоб залишити коментар

Будьте першим, хто залишить коментар!

Читайте також

Laracon US 2026: відео першого дня вже доступне Рекомендовано
Новини 29 липня 2026

Laracon US 2026: відео першого дня вже доступне

У Бостоні стартував Laracon US 2026, і запис першого дня вже доступний. Головне з кейноуту: офіційний Laravel LSP для редакторів, Laravel Cloud деплоїть Hono, Flask, Go та Rails, Pest 5 із Tia Engine. Аарон Френсіс приєднався до команди Laravel.

Pest 5: Tia Engine, плагін для AI-агентів і evals для LLM
Новини 29 липня 2026

Pest 5: Tia Engine, плагін для AI-агентів і evals для LLM

На першому дні Laracon US 2026 Нуно Мадуро представив Pest 5. Головне - Tia Engine, що переганяє лише зачеплені змінами тести й скорочує десятихвилинний прогін до кількох секунд, плюс плагіни для AI-агентів, evals, PHPStan і Rector.

Вакансії за темою

Middle QA Engineer, Manual QA, Fintech

Ручне тестування фінтех-продукту (web, mobile, API) з фокусом на функціональне, регресійне та модульне тестування. Вимоги: досвід тест-дизайну, знання SDLC/STLC, робота з Jira/Postman/DevTools, створення тестової документації. Преферуються знання фінансових систем та досвід з fintech-продуктами.

Пакети за темою

Aimeos Laravel

aimeos/aimeos-laravel

Cloud-native, API-first Laravel пакет для електронної комерції з інтегрованою штучною інтелектуальністю для надшвидких онлайн-магазинів, маркетплейсів та складних B2B проектів.

8,669 2026.04.1 13 4

Laravel Query Builder

spatie/laravel-query-builder

Легко будуйте Eloquent-запити на основі запитів від API.

4,455 7.3.0 13 9