Caching Partial View with View Composer in Laravel
Laravel 4 has got pretty nice Cache mechanism. Unfortunately, it’s nicety brings not too much functionality. It lacks a way to cache whole pages or partials.I have found nice plugin called Flatten which works on top of Laravel Cache and is able to do the job. What I desired was to cache partial view and also cache it’s data being created by View Composer.
My partial view is called menu. I aggregate product categories from ElasticSearch database to just present them in this menu. So I want to avoid two things:
- category aggregation from database
- creation of menu template
Having my view:
@cache('menu', 10)
<ul>
@foreach ($categories as $category)
<li>{{ $category['name'] }}</li>
@endforeach
</ul>
@endcache
I want to access categories only when Flatten does not have valid cache for this partial (cache is for 10 minutes).
For this I create View Composer:
class MenuPartialComposer {
public function compose($view) {
$categories = ESProducts::aggregateCategories();
$view->with('categories', $categories);
}
}
Unfortunately, Laravel launches view composer every time it hits partial creation during View::make() call. To prevent from database aggregation I dig into the Flatten code and did the following:
class MenuPartialComposer {
public function compose($view) {
if (Cache::has('flatten-section-menu')) {
return;
}
// do the rest here
}
}
So the final result is that I cache the view but I do not do the same with aggregated data.Instead I just avoid aggregation when partial is already cached. I believe this solution is just a workaround but I couldn’t find better way without modifying the library. Certainly, it would be better to Flatten having API designed for such case.