やんごとなき理由で静的ページっぽく扱う部分がある時に知っておくと便利な方法です。public 以下に置きたくない、拡張子抜きでのアクセスをwebサーバーの設定変更せずに実現したい、ミドルウェアだけ使いたい、などそういった場合に出番があります。これは次の様にできます。
<?php
/** @var string $baseDir 静的ファイルっぽくあつかう blade ファイルが置いてあるディレクトリのフルパス */
$baseDir = resource_path('views/docs');
// ↑で指定したディレクトリ内のファイルとディレクトリを再帰的に探索してそれの \SplFileInfo を foreach で回す
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($baseDir));
/** @var \SplFileInfo $fileinfo */
foreach ($iterator as $fileinfo) {
if ($fileinfo->isDir()) {
// ディレクトリに用はないのでスキップ
// コンポーネントファイルなど何かしら他にスキップしたいものがあればここの if に or で結ぶ
continue;
}
// blade ファイルのファイル名から、探索している範囲のルートディレクトリのパスと拡張子を除去
// 次の様になる
// /work/backend/KAISHA_WEB/resources/view/docs/user/profile/address.blade.php
// ↓
// /user/profile/address
$name = str_replace([$baseDir, '.blade.php'], '', $fileinfo->getPathname());
// $name の URL に $name を元にした名前で view を呼び出す処理を割り振る
// Laravel がいい感じに view 呼び出し用の名前に正規化してくれるので / が残ったままでもOK
Route::get($name, static fn () => view('docs'.$name));
// もし $name が /index で終わるなら、ディレクトリ相当のアクセスでも index ページが表示される様にルーティング定義を追加
if (str_ends_with($name, '/index')) {
Route::get(str_replace('index', '', $name), static fn () => view('docs'.$name));
}
}
view を返したいファイルを探索し、探索結果のファイルパスを元に URL と view 呼び出しを構築します。これを使えば同じようなルーティング定義をコピペしまくる必要がなくなります。
注意点としてルーティングキャッシュの取り扱いがあります。Laravel のphp artisan route:cacheコマンドはコマンド実行時点のルーティングを静的ファイルにまとめます。このため、このコードは動的にルーティングを構築していますが、キャッシュが生成された後はキャッシュに従うのみで、自動で読み込まれる領域にファイルをおいてもルーティングが増えません。その場合php artisan route:clearコマンドでルーティングのキャッシュを消す必要があります。