Во-первых, добавьте в таблицу pages столбец parent_id (nullable, default null, связь на pages->id).
Во-вторых, в модели Page настройте связи на pages (HasMany).
По поводу роутов одно из решений это парсинг URL-адреса.
// routes/web.php в самом конце
Route::get('{slug}', 'Controller@parse')->where('slug', '([0-9A-Za-z-/]+)');
// прикладываю один из своих рабочих вариантов. тут парсятся не только страницы, но и категории (с мультивложенностью), продукты
// app/http/controllers/controller.php
public function parse(Request $request) {
$urlArray = explode('/', $request->path());
if (count($urlArray) === 1) {
$page = Page::where('slug', $urlArray[0])->first();
if (!empty($page)) {
return (new PageController)->show($page);
}
$category = Category::where('slug', $urlArray[0])->where('parent_id', 1)->first();
if (!empty($category)) {
return (new CategoryController)->show($request, (new ProductFilters($request)), $urlArray[0]);
}
} else {
$parentCategory = NULL;
$i = 1;
foreach ($urlArray as $urlArrayItem) {
$lastStep = $i === count($urlArray);
$category = Category::where('slug', $urlArrayItem);
if (is_null($parentCategory)) {
$category->where('parent_id', 1);
} else {
$category->where('parent_id', $parentCategory->id);
}
if (empty($category->first())) {
if ($lastStep) {
$product = $parentCategory->products()->where('slug', $urlArrayItem)->active()->first();
if (!empty($product)) {
return (new ProductController)->show($urlArrayItem);
}
}
abort(404);
} else {
if ($lastStep) {
return (new CategoryController)->show($request, (new ProductFilters($request)), $urlArrayItem);
}
$parentCategory = $category->first();
}
$i++;
}
}
abort(404);
}