http://hoge.com/path/to/abc.jpg
を
http://hoge.com/path/to/abc.jpg.cnv?thumb=300x200
でサムネイル
http://hoge.com/path/to/abc.jpg.cnv?crop=300x200
で切り出し
http://hoge.com/path/to/abc.jpg.cnv?fit=300x200-top
で最適切り出し
したりします。
2019/01/23 追加
- サムネイルを無限生成できちゃうので、ファイル単位で制限を設定しましたー
- laravelのcache機構を導入しましたー
@mikkame さんありがとございます
2019/01/24 追加
- cacheに関する記述追加
設定方法
初期設定
interventionインストール
$ php composer.phar require intervention/image #interventionインストール
.env の設定
.env
CACHE_DRIVER=array #ローカルでキャッシュを無効にする場合
CACHE_DRIVER=file #fileベースでキャッシュする場合
CACHE_DRIVER=redis #redisを使う場合
ImageRouting.php
どこかに配置します。
app/Services/ImageRouting.php
<?php
namespace App\Services;
use Cache;
use Illuminate\Http\Request;
use Intervention\Image\Image;
class ImageRouting
{
/**
* @param string $imagePath 画像のフルパス
* @param Request $request
* @param string $extension 識別用の拡張子
* @param int $limit 生成件数制限
* @param int $cacheDays キャッシュ保持期間
* @return mixed
*/
function __invoke(
string $imagePath,
Request $request,
string $extension = '.cnv',
int $limit = 10,
int $cacheDays = 3
)
{
$imagePath = str_replace($extension, '', $imagePath);
$counterCache = md5($imagePath);
$fileCache = md5(json_encode([$imagePath, $request->all()]));
if (Cache::get($counterCache, 0) < $limit) {
$image = Cache::remember($fileCache, 60 * 24 * $cacheDays,
function () use ($request, $imagePath, $counterCache) {
$image = \Image::make(public_path($imagePath));
$image = $this->fitIfNeeded($image, $request);
$image = $this->cropIfNeeded($image, $request);
$image = $this->thumbnailIfNeeded($image, $request);
Cache::increment($counterCache);
return $image->response('jpg');
});
return $image;
} else {
abort(404);
}
}
/**
* hoge.cnv.jpg?fit=300x200-top (収まるようにトリミング)
* @param $image
* @param $request
* @return Image
*/
private function fitIfNeeded(Image $image, Request $request): Image
{
//chukyo.jpg_?fit=300x200-top (収まるようにトリミング)
$fit = $request->f ?: $request->fit;
if ($fit && preg_match('/([0-9]+)x([0-9]+)(:?-([-a-z]+))?/', $fit, $mc)) {
$image->fit($mc[1], $mc[2], function ($constraint) {
$constraint->upsize();
}, !empty($mc[3]) ? $mc[3] : 'center');
}
return $image;
}
/**
* hoge.cnv.jpg?crop=300x200 (切り出す)
* @param $image
* @param $request
* @return Image
*/
private function cropIfNeeded(Image $image, Request $request): Image
{
//chukyo.jpg_?crop=300x200 (切り出す)
$crop = $request->c ?: $request->crop;
if ($crop && preg_match('/([0-9]+)x([0-9]+)/', $crop, $mc)) {
$image->crop($mc[1], $mc[2]);
}
return $image;
}
/**
* hoge.cnv.jpg?thumb=300x200 (収まるように縮小)
* @param Image $image
* @param Request $request
* @return Image
*/
private function thumbnailIfNeeded(Image $image, Request $request): Image
{
$thumb = $request->t ?: $request->thumb;
if ($thumb && preg_match('/([0-9]+)x([0-9]+)/', $thumb, $mc)) {
if ($image->width() < $image->height()) {
$image->resize($mc[1], null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
});
} else {
$image->resize(null, $mc[2], function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
});
}
}
return $image;
}
}
routes/web.php に追加
routes/web.php
use Illuminate\Http\Request;
Route::get('{imagePath}', function ($imagePath, Request $request, \App\Services\ImageRouting $service) {
return $service($imagePath, $request);
})->where('imagePath', '(.*).cnv.(jpg|jpeg|png|gif)$');