Intervention Image リサイズ
- 前提
ShopControllerへ記述
$request->imageでviewで指定したname属性を取得することで画像を取得できる
$imageFile = $request->image;
画像がnullでなかったら && isValidでアップロードできたか判定
if(!is_null($imageFile) && $imageFile->isValid())
uniqidを生成し、rand関数で重複しないランダムなファイル名を作成
$fileName = uniqid(rand().'_');
- uniqidとは
PHPで用意されているユニークIDを生成する関数。
現在時刻を元にしているので、複数のサーバで同じ時刻で、uniqidを実行すると同じ値が生成されてしまうので注意が必要。
この問題はrand関数を利用してランダムな値を指定することで回避できる。
→画像やファイルのアップロード時、アップロードファイルを保存する際のファイル名の生成などで利用する。
※注意点としてはuniqidは暗号として脆弱なので、パスワードやトークンとして利用しない。
- 使い方
13文字の文字列が生成される
echo uniqid();
//実行結果例:36edrw3462fdr2
乱数を使い重複のリスクを減らす
echo uniqid(rand());
//実行結果例:92131575158af91ba5a22c
「ランダム数値_」に続いて13文字で生成された文字列が出力される
echo uniqid(rand().'_');
//実行結果例:"1423825616_63984841e3091"
アップロードしてきた画像$imageFileのextensionで拡張子を取得
$extension = $imageFile->extension();
作成したファイル名と拡張子をくっつける
$fileNameToStore = $fileName. '.' . $extension;
makeでInterventionImageを使えるようにして必要な値として$imageFile→resizeでサイズ指定してencodeする
$resizedImage = InterventionImage::make($imageFile)->resize(1920, 1080)->encode();
dd($imageFile,$resizedImage);
ddで見ると、リサイズ後に型が変わっていることがわかる
Illuminate\Http\UploadedFile
→Intervention\Image\Image
保存処理
Storage::putFile
ではFileオブジェクトを想定しており、InterventionImageでresizeすると
画像として扱われ、型が変わるのでStorage::put
で保存する必要がある。
フォルダがない場合→自動生成。ファイル名は指定する必要がある。
Storage::put('public/shops/' . $fileNameToStore, $resizedImage );
<?php /** * shop画像アップロード画面遷移+更新 * @param $request * @param $id */ public function edit(Request $request, $id) { if($request->isMethod('get')){ $this->viewData['shop'] = Shop::findOrFail($id); return view('owner.shops.edit', $this->viewData); } if($request->isMethod('post')){ $imageFile = $request->image; if(!is_null($imageFile) && $imageFile->isValid()){ //Storage::putFile('public/shops', $imageFile);リサイズなしの場合 $fileName = uniqid(rand().'_'); $extension = $imageFile->extension(); $fileNameToStore = $fileName. '.' . $extension; $resizedImage = InterventionImage::make($imageFile)->resize(1920, 1080)->encode(); //dd($imageFile,$resizedImage); Storage::put('public/shops/' . $fileNameToStore, $resizedImage ); } } return redirect()->route('owner.shops.index'); }
リファクタリング
商品画像をアップロードする場合など追加するときに、もう1度同じコードを書かなければいけないので、
重複を防ぐためにもサービスへコードの切り出しを行う。
引数に取得した画像である$imageFile
と、
画像を保存する際に'public/shops/'に保存していたが、商品画像アップロード時はproducts
フォルダに保存したいので、引数でフォルダ名もってきたいので$folderName
とする。
shops
のところを引数ではいってきた$folderName
に変えたいので
Storage::put('public/shops/' . $fileNameToStore, $resizedImage );
→
Storage::put('public/'. $folderName . '/' . $fileNameToStore, $resizedImage );
とする。
shop情報を保存する際に、作成したファイル名が必要になるので、戻り値として$fileNameToStore
を設定する。
<?php namespace App\Services\Image; use Illuminate\Support\Facades\Storage; use InterventionImage; Class ImageService { public static function addByImage($imageFile,$folderName){ $fileName = uniqid(rand().'_'); $extension = $imageFile->extension(); $fileNameToStore = $fileName. '.' . $extension; $resizedImage = InterventionImage::make($imageFile)->resize(1920, 1080)->encode(); Storage::put('public/'. $folderName . '/' . $fileNameToStore, $resizedImage ); return $fileNameToStore; } }
ShopControllerでメソッド化
サービスのuse文を追加する。use App\Services\Image\ImageService;
引数に$imageFile
,フォルダ名のshops
を渡す。
→戻り値を意識して$fileNameToStore
へ格納する。
$fileNameToStore = ImageService::addByImage($imageFile, 'shops');
<?php use App\Services\Image\ImageService; public function edit( UploadImageRequest $request, $id) { if($request->isMethod('get')){ $this->viewData['shop'] = Shop::findOrFail($id); return view('owner.shops.edit', $this->viewData); } if($request->isMethod('post')){ //$request->imageでname属性を取得することで画像を取得できる $imageFile = $request->image; //画像がnullでなかったら && isValidでアップロードできたか判定 if(!is_null($imageFile) && $imageFile->isValid()){ $fileNameToStore = ImageService::addByImage($imageFile, 'shops'); } } return redirect()->route('owner.shops.index'); }