それはどんな気持ちか
- ルートを変更する度にsitemapの更新したくないな
- 特定のミドルウェアルートグループのgetルートが全てsitemap.xmlに勝手に登録されたらいいのにな
※ 未解決
全てのルートの取得方法の確認も合わせてやってみます。
やってみる
想定する流れ
- ルートを取得する
- sitemap.xmlに出力
ルートを取得する
参考
このコマンドでやっていることが参考になりそうなので、参考にしてみる。
$ php artisan route:list
Illuminate\Foundation\Console\RouteListCommand
を読む。
// ※ use Illuminate\Routing\Router;
/**
* Create a new route command instance.
*
* @param \Illuminate\Routing\Router $router
* @return void
*/
public function __construct(Router $router)
{
parent::__construct();
$this->router = $router;
}
/**
* Execute the console command.
*
* @return void
*/
public function handle()
{
if (empty($this->router->getRoutes())) {
return $this->error("Your application doesn't have any routes.");
}
if (empty($routes = $this->getRoutes())) {
return $this->error("Your application doesn't have any routes matching the given criteria.");
}
$this->displayRoutes($routes);
}
$this->router->getRoutes()
で全てのルートを取得し、ルート毎に属性(name,middlewareなど)をそれぞれ処理している。
今回はミドルウェアとメソッドが欲しいのでそれらを確認してみます。
-
ミドルウェアの取得は
RouteListCommand/** * Get before filters. * * @param \Illuminate\Routing\Route $route * @return string */ protected function getMiddleware($route) { return collect($route->gatherMiddleware())->map(function ($middleware) { return $middleware instanceof Closure ? 'Closure' : $middleware; })->implode(','); }
ルート毎にミドルウェアを取得(gatherMiddleware)してクロージャかの判断などしつつコレクション化しているようです。
-
メソッドの取得は
RouteListCommand/** * Get the route information for a given route. * * @param \Illuminate\Routing\Route $route * @return array */ protected function getRouteInformation(Route $route) { return $this->filterRoute([ 'domain' => $route->domain(), 'method' => implode('|', $route->methods()), 'uri' => $route->uri(), 'name' => $route->getName(), 'action' => ltrim($route->getActionName(), '\\'), 'middleware' => $this->getMiddleware($route), ]); }
$route->methods()
で取れるようです。
取得してみる
とりあえずコントローラに直接書いてみます。
<?php
namespace App\Http\Controllers;
use Illuminate\Routing\Router;
class SiteMapController extends Controller
{
/**
* @var Router
*/
private $router;
public function __construct(Router $router)
{
$this->router = $router;
}
public function index()
{
$uris = [];
foreach ($this->router->getRoutes() as $route) {
if (!in_array('front', $route->gatherMiddleware()) || !in_array('GET', $route->methods()))
continue;
$uris[] = $route->uri;
}
}
}
取得出来る$urisはこんなかんじになる
[
0 => "/"
1 => "article/{Article}"
2 => "neko"
3 => "inu"
]
問題
ルートパラメータの存在するルートを全て取得する方法を見つけられていない、のでここでは一度無視する🐛
モデル結合ルートに限れば、既に存在するURIは定義されているということになるはずなので、その辺でうまいこと取得出来ないだろうかと考えています。
もう少し検証しますが、いい方法があったら教えて欲しいです。
sitemap.xmlに出す
<?php
namespace App\Http\Controllers;
use Illuminate\Routing\Router;
use Illuminate\Support\Facades\Response;
class SiteMapController extends Controller
{
/**
* @var Router
*/
private $router;
public function __construct(Router $router)
{
$this->router = $router;
}
public function index()
{
$uris = [];
foreach ($this->router->getRoutes() as $key => $route) {
if (!in_array('front', $route->gatherMiddleware()) || !in_array('GET', $route->methods()))
continue;
$uris[] = $route->uri;
}
$view = view('site_map.index', compact('uris'));
return Response::make($view, '200')->header('Content-Type', 'application/xml');
}
}
<?php echo '<?xml version="1.0" encoding="UTF-8" ?>' . "\n"; ?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
@foreach($uris as $uri)
<url>
<loc>{{ url($uri) }}</loc>
<changefreq>daily</changefreq>
</url>
@endforeach
</urlset>
おわり
楽したいのでもっとうまい方法考えます。
ただ些細な更新ストレスを減らすための行為で制限を増やすと逆説的にストレスが増えちゃいそうなので、laravelが素直に出来る範囲ぐらいの程々で諦めるべきかもしれません。