前回、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'));メルマガ購読の申し込みはこちらから。