---
title: "Практичний посібник з обробки зображень в Laravel"
url: https://laravelukraine.com/blog/prakticnii-posibnik-z-obrobki-zobrazen-v-laravel
date: 2026-07-24
source: https://laravel-news.com/a-practical-guide-to-laravels-first-party-image-processing?utm_medium=feed&utm_source=feedpress.me&utm_campaign=Feed%3A+laravelnews
---

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

Laravel 13.20 представив власний компонент обробки зображень через новий `Illuminate\Image` у [Pull Request #59276](https://github.com/laravel/framework/pull/59276). До цього релізу для зміни розміру аватара або конвертації завантаженого файлу в WebP доводилося використовувати сторонні пакети.

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

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

Драйвери GD та Imagick базуються на [Intervention Image](https://github.com/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](https://laravel-news.com/laravel-13-20-0), і ви можете переглянути повну реалізацію в [Pull Request #59276](https://github.com/laravel/framework/pull/59276) на GitHub.
