手順
1. Intervention Image をインストール
まず、Intervention Image ライブラリをインストールします。
composer require intervention/image
2-1. 画像の圧縮処理を実装(新規アップロード):サービスクラス
✅の箇所
/Applications/MAMP/htdocs/Laravel/collections/app/Service/Admin/CollectionService.php
namespace App\Service\Admin;
use App\Models\Collection;
use App\Models\CollectionImage;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Intervention\Image\ImageManager; // ✅
use Intervention\Image\Encoders\JpegEncoder; // ✅
use Intervention\Image\Drivers\Gd\Driver; // ✅
public static function storeRequestImage($request, $collection)
{
$orderData = json_decode($request->input('image_order'), true) ?? [];
$sessionTmpImages = $request->input('tmp_images');
// ✅ `ImageManager`を`gd`ドライバー指定で作成
$manager = new ImageManager(new Driver());
// 🔹 通常アップロードされた画像の保存
if($request->hasFile('image_path') && is_null($sessionTmpImages)) {
$uploadedFiles = $request->file('image_path');
foreach($uploadedFiles as $imagePath) {
$fileName = trim($imagePath->getClientOriginalName()); // アップロードファイル名取得
$order = collect($orderData)->first(fn($item) => str_starts_with($item['uniqueId'], $fileName)); // position取得
$imageName = time() . '_' . uniqid() . '.' . $imagePath->getClientOriginalExtension(); // テーブル保存用
// ✅ 拡張子を取得(小文字変換)
$extension = strtolower($imagePath->extension());
// ✅ 画像に合わせた拡張子選択
switch ($extension) {
case 'png':
$encoder = new PngEncoder(9); // PNG 圧縮
break;
case 'webp':
$encoder = new WebpEncoder(80); // WebP 圧縮
break;
default:
$encoder = new JpegEncoder(75); // それ以外はJPEG(品質75)
}
// ✅ 画像を圧縮
$compressedImage = $manager->read($imagePath->getRealPath())->encode($encoder);
// ✅ 圧縮画像を保存
Storage::disk('public')->put('collection_images/' . $imageName, (string)$compressedImage);
CollectionImage::create([
'collection_id' => $collection->id,
'image_path' => $imageName,
'position' => $order ? $order['position'] : 0
]);
}
}
2-2. 画像の圧縮処理を実装(セッション+ストレージのアップロード):リクエストクラス
✅の箇所
/Applications/MAMP/htdocs/Laravel/collections/app/Http/Requests/CollectionRequest.php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Storage;
use Intervention\Image\ImageManager; // ✅
use Intervention\Image\Drivers\Gd\Driver; // ✅
use Intervention\Image\Encoders\JpegEncoder; // ✅
use Intervention\Image\Encoders\PngEncoder; // ✅
use Intervention\Image\Encoders\WebpEncoder; // ✅
class CollectionRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return [
'title' => ['required', 'string', 'max:50'],
'description' => ['nullable', 'string', 'max:10000'],
'url_qiita' => ['nullable', 'url', 'max:500'],
'url_webapp' => ['nullable', 'url', 'max:500'],
'url_github' => ['nullable', 'url', 'max:500'],
'is_public' => ['required', 'boolean'],
'position' => ['required', 'integer'],
'image_path' => ['nullable'],
'image_order' => ['nullable'],
];
}
protected function failedValidation(\Illuminate\Contracts\Validation\Validator $validator)
{
// ✅ GDドライバーで ImageManager を作成
$manager = new ImageManager(new Driver());
$tmpImagePaths = session('tmp_images', []);
$fileNames = session('file_names', []);
$imageOrder = session('image_order', []);
// フォームの hidden input から画像順序データを取得
if($this->has('image_order')) {
$imageOrder = json_decode($this->input('image_order'), true);
}
if ($this->hasFile('image_path')) {
$images = $this->file('image_path');
foreach ($images as $image) {
// $base64Image = 'data:image/' . $image->extension() . ';base64,' . base64_encode(file_get_contents($image->getRealPath()));
$fileName = $image->getClientOriginalName(); // ファイル名取得
$extension = strtolower($image->extension()); // 拡張子を取得(小文字変換)
// ✅ 画像に合わせた拡張子を選択
switch ($extension) {
case 'png':
$encoder = new PngEncoder(9); // PNG 圧縮
break;
case 'webp':
$encoder = new WebpEncoder(80); // WebP 圧縮
break;
default:
$encoder = new JpegEncoder(75); // それ以外はJPEG(品質75)
}
// ✅ 画像を圧縮
$compressedImage = $manager->read($image->getRealPath())->encode($encoder);
$tmpImageName = time() . '_' . uniqid() . '.' . $extension;
Storage::disk('public')->put("tmp/{$tmpImageName}", (string)$compressedImage);
$tmpImagePaths[] = "tmp/{$tmpImageName}";
$fileNames[] = $fileName;
// `imageOrder` に `fileName` がすでに存在するかチェック
$foundIndex = array_search($fileName, array_column($imageOrder, 'fileName'));
if ($foundIndex !== false) {
// すでに `imageOrder` に登録済みなら `src` を更新
$imageOrder[$foundIndex]['src'] = "tmp/{$tmpImageName}";
} else {
// 新規画像の場合
$imageOrder[] = [
'fileName' => $fileName,
'src' => "tmp/{$tmpImageName}",
];
}
}
}
// セッションに保存
Session::put('tmp_images', $tmpImagePaths);
Session::put('file_names', $fileNames);
Session::put('image_order', $imageOrder);
parent::failedValidation($validator);
}
}