Laravelのurl()
やasset()
関数は大変便利なツールで、アプリ内の遷移やファイルのパス指定に欠かせない存在。
キャッシュ対策で画像やcssやjsファイルになどバージョンをコントロールしたり、デフォルトのルートパラメータを指定したりするには、デフォルトのUrlGenerator
(aliasはurl
)というClassを継承しないといけない。
通常、app()->singleton('url', \App\My\UrlGenerator::class);
で自前のUrlGenerator
で既存のコンポーネントを上書きできるが、url
に絡まるコンポーネントが異常に多いので、そう簡単にはいけなかった。
調べたところ、フレームワークは次のようにurl
コンポーネントを登録している:https://github.com/laravel/framework/blob/1003c27b73f11472c1ebdb9238b839aefddfb048/src/Illuminate/Routing/RoutingServiceProvider.php#L49
それを参考してApp\Providers\AppServiceProvider::boot
に自前の\App\My\UrlGenerator
を登録:
$this->app->singleton('url', function ($app) {
$routes = $app['router']->getRoutes();
$app->instance('routes', $routes);
// 自前のClass
$url = new \App\My\UrlGenerator(
$routes,
$app->rebinding('request', function ($app, $request) {
$app['url']->setRequest($request);
}),
$app['config']['app.asset_url']
);
$url->setSessionResolver(function () {
return $this->app['session'];
});
$url->setKeyResolver(function () {
return $this->app->make('config')->get('app.key');
});
$app->rebinding('routes', function ($app, $routes) {
$app['url']->setRoutes($routes);
});
return $url;
});
\App\My\UrlGenerator
はこんな感じ:
<?php
namespace App\My;
class UrlGenerator extends \Illuminate\Routing\UrlGenerator
{
/**
* @param string $path
* @param null $secure
* @return string
*/
public function asset($path, $secure = null)
{
$path_parts = pathinfo($path);
if (!in_array($path_parts['extension'], ['js', 'css'])) {
return parent::asset($path);
}
$v = config('app.version', 0);
if (config('app.env') != 'production') {
// ランダム
$v = md5(microtime(uniqid()));
}
$path .= '?v=' . $v;
return parent::asset($path, $secure);
}
}
そうすると、asset('/js/app.js')
すれば、勝手に?v=(...)
が付くようになる。
もちろん、開発者次第でいろんなカスタマイズができる。参考まで!