前回、validate()のソースコードで登場したマクロ、今回は有用なマクロの活用の例を紹介します。
マクロに関してのLaravelのマニュアルでは以下で、response()のマクロの例が紹介されています。
https://laravel.com/docs/5.5/responses#response-macros
これを見て「あ、これはここで使える!」と思ったのは、コントローラから出力するHTMLの中身の画像のURLの変換です。
まずは、ちょっと背景説明を。
私のお客さんのサイトでは画像がかなり多いので、サーバー(EC2)の負担を減らすために画像はすべてAWSのS3にアップしています。どれだけアクセスがあっても画像はS3から配信されるのでサーバーが落ちる心配もないし、サーバーをアップグレードする必要もなくコストセーブとなります。
しかし、ブレードを管理するデザイナーに、
<img src="/user/images/example.jpg">
のような参照を、
<img src="//example.s3.amazonaws.com/user/images/example.jpg">
と毎回書き換えてもらうのは、やっかい。もちろん、エディターやsassとかでのプリ処理は可能だけれども、1つステップ増えるしプログラマでないデザイナーにはちょっと。また、S3のURLも本サイトと開発サイトでは変えたいケースもあり、そうしてもらうとこちらも困ります。
ということで、出力時にダイナミックに変えるのは必須となりました。ダイナミックに変えるには、ウェブサーバーでの設定でも可能ですが、やはり、HTMLの中にS3のURLが入るのがサーバーにも負担にならず、ユーザーにとっても表示速度の点で最適です。
このために、以下のようなユーザー定義のヘルパーを作成して、
// Lobは、私の会社 Lots of Bytesの略です。
class Lob {
...
public static function view($view, $data)
{
$host = '//example.s3.amazonaws.com';
$html = View::make($view)->with($data)->render());
$output = preg_replace('#/user/images/#', $host.'/user/images/, $html);
return response($output);
}
...
}
コントローラで以下のように、コールしていました。
return Lob::view('user/product', compact('page', 'product'));
これで用は足りるのですが、なんかLaravelらしくない。
そこで、マクロの登場です。
app/Providers/AppServiceProvider.phpを編集して、viewWithS3のマクロを定義します。
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\View;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Schema::defaultStringLength(191);
Response::macro('viewWithS3', function ($view, $data) {
$host = '//example.s3.amazonaws.com';
$html = View::make($view)->with($data)->render());
$output = preg_replace('#/user/images/#', $host.'/user/images/, $html);
// 以下の$thisは、AppServiceProviderのインスタンスでなく、Illuminate\Http\Response
return $this->make($output);
});
}
...
}
コントローラでは、以下のようにコールします。Laravelらしくわかりやすくなりましたね。
return response()->viewWithS3('user/product', compact('page', 'product'));
メルマガ購読の申し込みはこちらから。
