class DynamicRoutes
{
public function routes(): void
{
/** @var Collection $pageCollection */
$pageCollection = getFromCacheIf(config('cache.pages'), CACHE_PAGES, function () {
try {
return $this->getPages();
} catch (\Exception $exception) {
return new Collection();
}
});
$pageCollection->each(function (Page $page) use ($pageCollection) {
$routeName = ROUTE_PREFIX_PAGE.$page->slug;
$routeUri = $page->getAttribute('url');
$parentRouteName = $page->parent_id
? ROUTE_PREFIX_PAGE.($pageCollection->get($page->parent_id)->slug)
: 'home';
Route::prefix($routeUri)->group(function () use ($page, $routeName, $parentRouteName) {
Route::get('', static function () use ($page) {
return App::call($page->controllerName(), ['page' => Page::findOrFail($page->id)]);
})
->name($routeName)
->breadcrumbs(function (Trail $trail) use ($page, $routeName, $parentRouteName) {
return $trail->parent($parentRouteName)
->push($page->localizedAttribute('title'), route($routeName));
});
switch ($page->controllerName()) {
case GalleryController::class:
$this->galleryRoutes($routeName);
break;
case TourController::class:
$this->tourRoutes($routeName);
break;
case NewsController::class:
$this->newsRoutes($routeName);
break;
}
});
});
}
private function galleryRoutes(string $parentRouteName): void
{
Route::get('{gallery:slug}', [GalleryController::class, 'show'])
->name(ROUTE_GALLERY)
->breadcrumbs(function (Trail $trail, Gallery $gallery) use ($parentRouteName) {
return $trail->parent($parentRouteName)
->push($gallery->localizedAttribute('title'), route(ROUTE_GALLERY, $gallery));
});
}
private function tourRoutes(string $parentRouteName): void
{
Route::get('{tour:slug}', [TourController::class, 'show'])
->name(ROUTE_TOUR)
->breadcrumbs(function (Trail $trail, Tour $tour) use ($parentRouteName) {
return $trail->parent($parentRouteName)
->push($tour->localizedAttribute('title'), route(ROUTE_TOUR, $tour));
});
}
private function newsRoutes(string $parentRouteName): void
{
Route::get('{news:slug}', [NewsController::class, 'show'])
->name(ROUTE_NEWS)
->breadcrumbs(function (Trail $trail, News $news) use ($parentRouteName) {
return $trail->parent($parentRouteName)
->push($news->localizedAttribute('title'), route(ROUTE_NEWS, $news));
});
}
private function getPages(): Collection
{
$pages = Page::whereNotNull('slug')->get()->keyBy('id');
$pages->each(function (Page $page) use ($pages) {
$page->setAttribute('url', $this->buildUrlForPage($page, $pages));
});
return $pages;
}
private function buildUrlForPage(Page $page, Collection $pages): string
{
if (!$page->parent_id) {
return $page->slug;
}
$parentPage = $pages->get($page->parent_id);
return $this->buildUrlForPage($parentPage, $pages).'/'.$page->slug;
}
}
router/web.php
//...
app(DynamicRoutes::class)->routes();
Route::fallback(function () {
return response()->view('errors.404', [], 404);
});