Nahrávání souborů - 2. část

V minulém díle jsme si vysvětlili a ukázali nahrávání obrázku ke článku. Jednalo se o velmi jednoduché řešení, které ale neumožňovalo nijak upravovat obrázek před jeho uložením. Tento problém vyřešíme pomocí knihovny Intervention Image, která nabízí mnoho možností, jak s obrázkem pracovat. Budeme pokračovat od minulého dílu, takže většinu kódu už máme připravenou.

Instalace

Pro instalaci použijeme klasicky composer:

$ composer require intervention/image

Intervention Image podporuje Laravel a nabízí service provider a fasádu pro jednoduchou integraci do projektu. Do souboru config/app.php přidejte nový alias do pole $aliases:

'Image' => Intervention\Image\Facades\Image::class

Balíček není potřeba vkládat do pole $providers, protože od verze Laravel 5.5 funguje auto-discovery, který nám knihovnu automaticky načte. Ve výchozím nastavení používá Intervention Image PHP rozšíření GD, které zpracovává všechny obrázky. Pokud budete chtít přejít na Imagick, můžete si nechat vygenerovat konfiguraci, kde si nastavení změníte:

$ php artisan vendor:publish --provider="Intervention\Image\ImageServiceProviderLaravel5"

Tím je prakticky hotova celá instalace a můžeme se vrhnout na upravu controlleru, protože to hlavní se bude dít právě v něm po odeslání formuláře.

Úprava controlleru

Jako první si v App\Http\Controllers\PostController přidáme náš alias pro Intervention Image, který jsme si definovali v config.php:

use Image;

Dále si upravíme metodu store(), protože právě tato metoda se volá po odeslání formuláře:

public function store(Request $request): RedirectResponse  
{  
	$this->validate($request, [  
		'text' => 'required',  
		'image' => 'image|max:1999'  
	]);  
  
	$originalImage = $request->image;  
    $imageName = uniqid().$originalImage->getClientOriginalName();
      
    $originalImage->storeAs('uploads/posts-images', $imageName);  
    $thumbnailImage = Image::make($originalImage);  
    $thumbnailImage->resize(300, 300);  
    $thumbnailImage->save(storage_path('app/public/uploads/thumbnails/') . $imageName);
      
    $post = new Post();  
    $post->content = $request->text;  
    $post->image_name = $imageName;  
    $post->save();
      
    return redirect('/');  
}

Úpravu projdu postupně. Jako první si z requestu vytáhnu obrázek a do proměnné $imageName si vygeneruji nový jedinečný název obrázku, aby se nám nestalo, že nahrajeme jiný obrázek se stejným názvem a původní obrázek tak přepíšeme. Protože si chceme uložit obrázek s vlastním pojmenováním, využijeme metodu storeAs, která jako první parametr přijímá cestu pro uložení a jako druhý parametr vložíme náš nový název obrázku.

Dále začneme pracovat s knihovnou Intervention Image. Jako první si statickou metodou make() inicializujeme nový objekt do proměnné $thumbnailImage. Poté následuje jedna z mnoha metod, které můžeme v knihovně využít. V našem případě využijeme metodu resize(), která nám obrázek zvětší či zmenší podle našich potřeb. A nakonec zavoláme metodu save(), do které vložíme adresu pro uložení. Abychom rozlišili původní a ořezaný obrázek, vytvořil jsem nový adresář storage/app/public/uploads/thumbnails, do kterého uložíme upravený obrázek.

Protože máme nyní dvě cesty a v nich uloženy obrázky s úplně totožným názvem, upravíme si v další části tabulku posts, v controlleru si nicméně můžeme už upravit sloupec na image_name, který již nebude obsahovat cestu obrázku, ale pouze jeho jedinečný název. Model pak klasicky uložíme.

Úprava migrace

V minulém díle jsme si vytvořili migraci pro tabulku posts, kde jsme předpokládali, že do ní budeme cestu k obrázku. To je nyní potřeba upravit, aby přijímala pouze název:

 public function up()
 {
        Schema::create('posts', function (Blueprint $table) {
            $table->increments('id');
            $table->text('content');
            $table->text('image_name');
            $table->timestamps();
        });
  }

Pokud chceme, aby se úprava projevila rovnou, pak můžeme jednoduše přegenerovat celou databázi a znovu zavolat všechny migrace:

$ php artisan migrate:refresh

Pokud je toto vaše poslední migrace, a chcete vykonat pouze tuto migraci, pak lze využit rollback:

$ php artisan migrate:rollback --step=1 // provede metodu down() na posledni migraci
$ php artisan migrate // znovu vykoname migraci, tentokrat jiz upravenou

Úprava pohledu

Jako poslední nám zbývá upravit pohled resources/views/posts.blade.php, který vypisuje články. Upravíme si adresu zdroje obrázku, aby se zobrazoval náš upravený obrázek:

 <img class="w-full" src="{{ 'storage/uploads/thumbnails/' . $post->image_name }}">

Závěr

Jak jsme mohli vidět, integrace a práce s knihovnou Intervention Image je velmi jednoduchá. Knihovna samozřejmě obsahuje mnoho jiných užitečných API, než je pouze zmenšení/zvětšení obrázku. Všechny možnosti najdete na jejich oficiálních stránkách, které se určitě vyplatí navštívit.

Není vám něco jasné, mám někde chybu nebo chcete přidat svůj názor na článek? Napište do komentářů pod článkem.