Laravel Cache:: Best Practices Laravel Cache:: Best Practices laravel laravel

Laravel Cache:: Best Practices


Many people do this differently but when best practices is a concern I believe the best place to do caching is in your repository.

Your controller shouldn't know too much about the data source I mean whether its coming from cache or coming from database.

Caching in controller doesn't support DRY (Don't Repeat Yourself) approach, because you find yourself duplicating your code in several controllers and methods thereby making scripts difficult to maintain.

So for me this is how I roll in Laravel 5 not so different if are using laravel 4:

//1. Create GalleryEloquentRepository.php in App/Repositories

<?php namespace App\Repositories;use App\Models\Gallery;use \Cache;/** * Class GalleryEloquentRepository * @package App\Repositories */class GalleryEloquentRepository implements GalleryRepositoryInterface{    public function all()    {        return Cache::remember('gallerys', $minutes='60', function()        {            return Gallery::all();        });    }    public function find($id)    {        return Cache::remember("gallerys.{$id}", $minutes='60', function() use($id)        {            if(Cache::has('gallerys')) return Cache::has('gallerys')->find($id); //here am simply trying Laravel Collection method -find            return Gallery::find($id);        });    }}

//2. Create GalleryRepositoryInterface.php in App/Repositories

<?php namespace App\Repositories;/** * Interface GalleryRepositoryInterface * @package App\Repositories */interface GalleryRepositoryInterface{    public function find($id);    public function all();}

//3. Create RepositoryServiceProvider.php in App/Providers

<?php namespace App\Providers;use Illuminate\Support\ServiceProvider;/** * Class RepositoryServiceProvider * @package App\Providers */class RepositoryServiceProvider extends ServiceProvider{    /**     * Indicates if loading of the provider is deferred.     *     * @var bool     */    //protected $defer = true;    /**     * Bootstrap the application services.     *     * @return void     */    public function boot()    {        //    }    /**     * Register the application services.     *     * @return void     */    public function register()    {        $this->app->bind(            'App\Repositories\GalleryRepositoryInterface',            'App\Repositories\GalleryEloquentRepository'        );    }}

//4. At the controller you can do this

<?php namespace App\Http\Controllers;use \View;use App\Repositories\GalleryRepositoryInterface;class GalleryController extends Controller {    public function __construct(GalleryRepositoryInterface $galleryInterface)    {        $this->galleryInterface = $galleryInterface;    }    public function index()    {        $gallery = $this->galleryInterface->all();        return $gallery ? Response::json($gallery->toArray()) : Response::json($gallery,500);    }}


Of course there are techniques that you can avoid putting cache logic within your controllers and hand it off to some third party packages to manage the caching for you.

I recommend you to take a look at this article

https://github.com/imanghafoori1/laravel-widgetize

This way you can organize your page partials into well defined and self cached widgets classes. so you will have granular control for cache configs, and you only have to set the "configs"(and not the caching logic). like "cache tags", "expiration period" and etc.The cache logic is written by some one else for you and extracted out into a well unit tested package. so it does not pollute you code.

The other advantage is that not only you save database queries in this way but you also save a lot of php code from running over and over again, for example the php code behind laravel blade does not need to be run and it doesn't when the widget is within the cache.