Reputation: 6663
I'm using a view composer to create my site's navigation structure. A few links in the navigation are dynamic and require a couple DB queries. All is fine, however, these DB queries are executed multiple times if I register the view composer with multiple views that are loaded on the same page (ex: a primary navigation view and secondary sidebar view). This is because Laravel instantiates my Navigation class every time one of the views is created, which is expected behavior.
However, I'd like to eliminate these duplicate queries. My first thought was to implement some sort of singleton pattern, but this won't work because of how Laravel's view composers work. Is there some way I can mimic a singleton pattern here? Or maybe a better way to eliminate these duplicate DB queries (disregarding HTML/file caching)?
Here's a quick snippet of what I'm sorta doing for people who like a visual:
View Composer registration:
View::composer(array('layouts.nav', 'layouts.sidebar'), '\Namespace\ViewComposers\Navigation');
/Namespace/ViewComposers/Navigation.php:
public function compose(View $view)
{
$navigation = array();
...
// Some code that requires DB queries
...
$view->navigation = $navigation;
}
/views/layouts/nav.blade.php:
@foreach($navigation as $nav)
...
@endforeach
/views/layouts/sidebar.blade.php:
@foreach($navigation as $nav)
...
@endforeach
Upvotes: 2
Views: 751
Reputation: 8029
There are many ways to do this, but one way would be to register the composer as a singleton with the IoC container. This works due to the fact that view composers are resolved from the IoC container.
App::singleton('MyProject\MyComposer');
namespace MyProject;
class MyComposer
{
protected $navigation;
public function compose($view)
{
$view->navigation = $this->getNavigation();
}
public function getNavigation()
{
if ($this->navigation !== null) {
return $this->navigation;
}
$results = ...;
return $this->navigation = $results;
}
}
Other solutions I won't outline here are to instead dependency inject a repository/service that caches results in memory, and use the query builder's remember()
method with the array cache driver.
Upvotes: 1