You are having to register routes on the fly, which wouldn't necessarily be efficient, and it is hiding your API - most devs will go straight to the web.php and api.php files to see the public API for your app, but yours is hidden in the RouteServiceProvider.
As an alternative, you could simply have a catch-all route for pages:
// all other route
Route::get('{page}', 'PageController@show');
You would basically be passing any unmatched URIs into thePageController's show method. You could change the key for finding a Page model to uri:
// Page.php
public function getRouteKeyName()
{
return 'uri';
}
Now, your show action can Route-Model bind a Page instance based on the uri (which as a result should be unique on the pages table):
// PageController.php
public function show(Page $page)
{
// since you already have the page, you can lazy-load the related sections
$page->load('sections');
return view('pages.show', ['page' => $page]);
}
Note: this has the limitation that a Page uri cannot be the same as another URI defined in your routes, because the other URI will be matched first, but you will suffer from that with your existing solution in any case.