Ok, I am totally re-writing this question, now that I am a bit more familiar with larval.
Here is my situation: I have a guitar lessons site based on larval 5.2.36, where each lesson belongs to a category, and within a lesson are several exercises. An exercise table does not have a category id as it is linked to a lesson which has a category.
Goal What I am trying to figure out is how to pass the category of the currently displayed lesson or exercise to a menu sidebar view that displays the categories, so that the category of the lesson or exercise is highlighted. For this, I need to understand how to do such a task in laravel.
From what I gathered, this is often done via controllers. However, there is no menu controller, but rather a menu composer. It contains a function
class MenuComposer
{
public function compose(View $view)
{
$minutes = 6 * 60;
$value = Cache::remember('menu-categories', $minutes, function() {
return \App\Category::with('parent')->with('children')->get();
});
$view->with('categories', $value);
}
}
Then in the menu blade file we have
@foreach ($categories as $category)
<?php $category = $category->present(); ?>
@if ($category->parent == null)
<li><a href="{{ $category->url }}">{{ $category->title }}</a></li>
@foreach ($category->children as $child)
<?php $child = $child->present() ?>
<li class="level1"><a href="{{ $child->url }}">{{ $child->title }}</a></li>
<?php
/*
@foreach ($child->children as $grandChild)
<?php $grandChild = $grandChild->present() ?>
<li class="level2"><a href="{{ $grandChild->url }}">{{ $grandChild->title }}</a></li>
@endforeach
*/
?>
@endforeach
@endif
@endforeach
So this is clear. I see that I can use the menu composer to pass additional data with a $view->with() call.
The question is how do I get the current category? For exercises and lessons, the routes don't have category data. They are of form
lesson/lessonid/lessontitle
or
exercise/exid/extitle
So I know I could do some sort of query of the model. But seems that wouldn't make sense, since I know there are other places in the process flow where the current cat is being passed. For instance, on an exercise page, the view is retrieving category as
$exercise->lesson->category->title
It is being passed this in exercise controller as
public function index($id, $name = null)
{
//$this->hit($id);
$exercise = $this->apiController->get($id);
$authorized = $this->isUserAuthorized();
return view('exercise/index', [
'exercise' => $exercise->present(),
'authorized' => $authorized,
]);
}
Similarly, a lesson controller passes $lesson object to lesson view as
public function index($id, $name = null)
{
//$this->hit($id);
$lesson = $this->apiController->get($id);
$subscribed = $this->request->user() && $this->request->user()->subscribed('premium');
return view('lesson/index', [
'lesson' => $lesson->present(),
'subscribed' => $subscribed,
]);
}
Based on above, seems I could modify the return statements in the lesson and exercise controller to pass the category to the menu view, but I don't see in the documentation how to do that, and I suspect the menu view is rendered before the lesson and exercise controller are called...
Also read about using service providers. middleware, etc, here: How to pass data to all views in Laravel 5?
But all these approaches seem overkill. I don't need every view to have the data. Seems to me, I need to do this somehow in the menu composer. But I don't know what method to use from the menu composer to retrieve the current lesson or exercise category. In the menu composer after debugging in phpstorm I see that the $view object for a lesson has $view->$data->$lesson->$entity.
So what I did was edited the menu composer to pass category to view:
$d=$view->getdata();
$s=array_key_exists ('lesson' , $d );
if ($s ==1) $attr = collect($d)->get('lesson');
$cat=$attr->cat();
This works since in the LessonPresenter I added function
public function cat()
{
$cat = $this->entity->category['attributes']['title'];
return $cat;
}
This works, but I feel like it is a hack. And I will have to do this for the Exercise Presenter as well. Being new to larval I suspect there has to be a more elegant way to do this. So can someone please explain how this should be done?
thanks,
Brian