I'll try and explain my issue with a simplified example.
- My app has "Levels" and "Topics".
- Inside the web.php I use DI to pass the releveant id (slug in my case) to the Controller method. So my urls look like
- exampleapp.com
- exampleapp.com/app/{level}
- exampleapp.com/app/{level}/{topic}
- Then the controller happily picks up the injected object and passes it on to the view
However... in the resources part of the application the views are split up into many components, partials and so on and therefore the objects injected are available in the main view loaded from the controller but not in the components
I understand these components/partials are separate views and I know that using a service provider along with View::creator and View::share I can share data into some or all of these. (I am doing this with a variable named all_levels. Which unsurprisingly gets all Levels.)
However I would like to use the AppServiceProvider (or some other solution) to pass the Object Data which is available from the URL to some of the views as it is done in the controller.
This would be useful say in Breadcrumbs or Navigation to highlight which page the user is on.
Soutions I've Tried
I've tried 2 different solutions, which both feel very messy
A) Use request()->path() in the ServiceProvider to get the appropriate parts and query to get the Level and Topic and pass to selected views using View::creator and View::share.
Pretty messy in the provider (especially my app is significantly more complicated than the example).
B) Pass the required data via a Component Attribute on the tag and use a __construct in the View/Component/BaseLayout.php
Feels unpleasant as each blade for each page must include this attribute.
I feel like there is some tidy and best practice Laravel way to achieve this, which I am missing.
Can anyone help?
web.php
Route::middleware('auth')->group(function () {
// Level pages
Route::prefix('app')->name('levels.')->group(function () {
Route::get('{level}', [LevelsController::class, 'show'])->name('show');
// Topic pages
Route::name('topics.')->group(function () {
Route::get('{level}/{topic}', [TopicsController::class, 'show'])->name('show');
TopicsController.php
public function show(Level $level, Topic $topic)
{
return view(
'pages.topics.show',
[
'level' => $level,
'topic' => $topic
]
);
}
AppServiceProvider.php
use App\Models\Level;
class AppServiceProvider extends ServiceProvider
{
public function register()
{
}
public function boot(Level $level)
{
View::creator(['*'], function ($view) {
$all_levels = Cache::rememberForever('all_levels', function () {
return Level::all();
});
View::share('all_levels', $all_levels);
});
}
}