Intervention Image リサイズ

  • 前提

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\UploadedFileIntervention\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');
    }