Laravel.io
Exemple of register:

    public function register()
    {        
        $this->app->bind('App\Product\Repository', function()
        {
            $eloquent = new \App\Repositories\Product\Eloquent(new App\Model\Product);
        
            if ($this->useCache)
            {
                return new \App\Repositories\Product\Cache($eloquent);
            }
            return $eloquent;
        });
    }

/***********************************************************************
 * Eloquent class used for all repositories of the project
 */

<?php namespace App\Repositories;

use \RuntimeException;
use \InvalidArgumentException;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;

abstract class Eloquent implements Repository
{
    
    /**
     * Model/Mapper to use to map to the data
     * 
     * @var object
     */
    protected $model;

    /**
     * Constructor
     * 
     * @param object $model
     * @throws InvalidArgumentException
     */
    public function __construct($model=null)
    {
        if (is_null($model) || empty($model))
        {
            throw new InvalidArgumentException('Invalid Mapper');
        }
        
        $this->model = $model;
    }
    
    /**
     * Get an item by its ID
     * 
     * @param $id
     * @param array $columns
     * @return mixed
     */
    public function getById($id, $columns = ['*']) 
    {
        if (is_null($id) || empty($id))
        {
            throw new InvalidArgumentException('Invalid id');
        }
        
        return $this->model->notDeleted()->find($id, $columns);
    }
    
    /**
     * Get an item identified a given attribute
     * 
     * @param $attribute
     * @param $value
     * @param array $columns
     * @return mixed
     */
    public function getBy($attribute=null, $value=null, $columns=['*']) 
    {
        if (is_null($attribute) || empty($attribute))
        {
            throw new InvalidArgumentException('Invalid attribute: '.$attribute);
        }
        
        return $this->model->notDeleted()->where($attribute, '=', $value)->first($columns);
    }

    /**
     * Return a collection of all saved items
     *
     * @param array $columns
     */
    public function getAll($columns=['*'])
    {
        return $this->model->notDeleted()->get($columns);
    }
    
    /**
     * Get all items identified a given attribute
     * 
     * @param $attribute
     * @param $value
     * @param array $columns
     * @return mixed
     */
    public function getAllBy($attribute=null, $value=null, $columns=['*']) 
    {
        if (is_null($attribute) || empty($attribute))
        {
            throw new InvalidArgumentException('Invalid attribute: '.$attribute);
        }
        
        return $this->model->notDeleted()->where($attribute, '=', $value)->get($columns);
    }
    
    /**
     * Get all paginated items
     * 
     * @param int $perPage
     * @param array $columns
     * @return mixed
     */
    public function getPaginate($perPage=15, $columns=['*']) 
    {
        $perPage = intval($perPage);
        if ($perPage==0)
        {
            throw new InvalidArgumentException('Invalid value per page');
        }
        
        return $this->model->notDeleted()->paginate($perPage, $columns);
    }

    /**
     * Create a new item
     *
     * @param array $data
     * @throws InvalidArgumentException
     * @return Authentication\Mappers\Eloquent saved object
     */
    public function create(array $data=[])
    {
        return $this->model->create($data);
    }

    /**
     * Update an existing item
     *
     * @param array $data
     * @param integer $id
     * @param string $attribute
     * @throws RuntimeException
     * @throws InvalidArgumentException
     * @return Eloquent saved object
     */
    public function update(array $data=[], $id=null, $attribute="id")
    {
        if (is_null($id) || empty($id))
        {
            throw new InvalidArgumentException('Invalid ID');
        }
        
        $model = $this->model->where('id', $id)->first();
        if (is_null($model) || !$model->exists)
        {            
            throw new InvalidArgumentException('Item not found');
        }

        try
        {
            $update = $model->where($attribute, '=', $id)->update($data);
        }
        catch(Exception $e)
        {
            throw new RuntimeException($e->getMessage(), $e);
        }

        if ($update===false)
        {
            throw new RuntimeException('Could not save the item');
        }
        
        return $update;
    }

    /**
     * Delete an item identified by a given id
     *
     * @param integer $id
     * @throws RuntimeException
     * @throws InvalidArgumentException
     * @throws RuntimeException
     */
    public function delete($id=null)
    {
        if (is_null($id) || empty($id))
        {
            throw new InvalidArgumentException('Invalid ID');
        }
        
        $model = $this->model->where('id', $id)->first();
        if (is_null($model) || !$model->exists)
        {
            throw new InvalidArgumentException('Item not found');
        }
        
        try
        {
            $delete = $model->delete();
        }
        catch(Exception $e)
        {
            throw new RuntimeException($e->getMessage(), $e);
        }

        if (!$delete)
        {
            throw new RuntimeException('Could not delete the item');            
        }
        
        return $model;
    }

    /**
     * Restore an item identified by a given id
     *
     * @param integer $id
     * @throws InvalidArgumentException
     * @throws RuntimeException
     */
    public function restore($id=null)
    {
        if (is_null($id) || empty($id))
        {
            throw new InvalidArgumentException('Invalid ID');
        }
        
        $model = $this->model->withTrashed()->where('id', $id)->first();
        if (is_null($model) || !$model->exists)
        {
            throw new InvalidArgumentException('Item not found');
        }
        
        try
        {
            $restore = $model->restore();
        }
        catch(Exception $e)
        {
            throw new RuntimeException($e->getMessage(), $e);
        }

        if (!$restore)
        {
            throw new RuntimeException('Could not restore the item');
        }
        
        return $restore;
    }

	/**
	 * Handle dynamic getBy call
	 *
	 * @param  string  $method
	 * @param  array   $parameters
	 * @return mixed
	 * @throws \BadMethodCallException
	 */
	public function __call($method, $parameters)
	{
	    if (Str::startsWith($method, 'getBy'))
	    {
	        $attribute = str_replace('getBy', '', $method);
	        $model = $this->model;
	        if ($model::$snakeAttributes)
	        {
	            $attribute = Str::snake($attribute);
	        }
    	    array_unshift($parameters, $attribute);
    	    return call_user_func_array([$this, 'getBy'], $parameters);
	    }
	    elseif (Str::startsWith($method, 'getAllBy'))
	    {
	        $attribute = str_replace('getAllBy', '', $method);
	        $model = $this->model;
	        if ($model::$snakeAttributes)
	        {
	            $attribute = Str::snake($attribute);
	        }
    	    array_unshift($parameters, $attribute);
    	    return call_user_func_array([$this, 'getAllBy'], $parameters);
	    }
	    
	    throw new \BadMethodCallException('Invalid method: '.$method);
	}
    
}


/***********************************************************************
 * Using the decorator pattern whe can make a cached implementation of this
 */

<?php namespace App\Repositories;

use \RuntimeException;
use \InvalidArgumentException;
use App\CacheRepository;
use Illuminate\Support\Facades\App;

abstract class Cache implements Repository
{
    
    /**
     * Repository
     * 
     * @var $repository
     */
    protected $repository;

    /**
     * Cache interface
     * 
     * @var Cache
     */
    protected $cache;

    /**
     * Constructor
     * 
     * @param Repository Repository
     * @param Cache $cache
     * @throws InvalidArgumentException
     */
    public function __construct(Repository $repository=null, CacheRepository $cache=null)
    {
        if (is_null($repository) || empty($repository))
        {
            throw new InvalidArgumentException('Invalid repository');
        }
        
        $this->repository = $repository;
        $this->cache = $cache;
    }

    /**
     * Get an item by its ID
     *
     * @param string $id
     * @throws InvalidArgumentException
     * @return mixed Eloquent object found or null if not found
     */
    public function getById($id=null)
    {
        if (is_null($id) || empty($id))
        {
            throw new InvalidArgumentException('Invalid id');            
        }

        $this->cache->setKey($this, __FUNCTION__, func_get_args());
        
        return $this->cache->get(function() use ($id) 
        {
            return $this->repository->getById($id);
        });
    }
    
    /**
     * Get an item identified a given attribute
     * 
     * @param $attribute
     * @param $value
     * @param array $columns
     * @return mixed
     */
    public function getBy($attribute=null, $value=null, $columns=['*']) 
    {
        if (is_null($attribute) || empty($attribute))
        {
            throw new InvalidArgumentException('Invalid attribute: '.$attribute);
        }

        $this->cache->setKey($this, __FUNCTION__, func_get_args());
        
        return $this->cache->get(function() use ($attribute, $value, $columns) 
        {
            return $this->repository->getBy($attribute, $value, $columns);
        });
    }

    /**
     * Return a collection of all saved items
     *
     * @return Illuminate\Support\Collection
     */
    public function getAll()
    {
        $this->cache->setKey($this, __FUNCTION__, func_get_args());
        
        return $this->cache->get(function() 
        {
            return $this->repository->getAll();
        });
    }
    
    /**
     * Get all items identified a given attribute
     * 
     * @param $attribute
     * @param $value
     * @param array $columns
     * @return mixed
     */
    public function getAllBy($attribute=null, $value=null, $columns=['*']) 
    {
        if (is_null($attribute) || empty($attribute))
        {
            throw new InvalidArgumentException('Invalid attribute: '.$attribute);
        }
        
        $this->cache->setKey($this, __FUNCTION__, func_get_args());
        
        return $this->cache->get(function() use ($attribute, $value, $columns)
        {
            return $this->repository->getAllBy($attribute, $value, $columns);
        });
    }

    /**
     * Create a new item
     *
     * @param array $data
     * @throws InvalidArgumentException
     * @return Eloquent saved object
     */
    public function create(array $data=Array())
    {
        $this->cache->flush();
        
        return $this->repository->create($data);
    }

    /**
     * Update an existing item
     *
     * @param array $data
     * @param integer $id
     * @throws RuntimeException
     * @throws InvalidArgumentException
     * @return Authentication\Mappers\Eloquent saved object
     */
    public function update(array $data=Array(), $id=null)
    {
        if (is_null($id) || empty($id))
        {
            throw new InvalidArgumentException('Invalid ID');
        }
        
        $update = $this->repository->update($data, $id);
        
        $this->cache->flush();
        
        return $update;
    }

    /**
     * Delete an item identified by a given id
     *
     * @param integer $id
     * @throws RuntimeException
     * @throws InvalidArgumentException
     * @throws RuntimeException
     */
    public function delete($id=null)
    {
        if (is_null($id) || empty($id))
        {
            throw new InvalidArgumentException('Invalid ID');
        }
        
        $delete = $this->repository->delete($id);
        
        $this->cache->flush();
        
        return $delete;
    }

    /**
     * Restore an item identified by a given id
     *
     * @param integer $id
     * @throws InvalidArgumentException
     * @throws RuntimeException
     */
    public function restore($id=null)
    {
        if (is_null($id) || empty($id))
        {
            throw new InvalidArgumentException('Invalid ID');
        }
        
        $restore = $this->repository->restore($id);
        
        $this->cache->flush();
    }
    
}

/***********************************************************************
 * Cache for repository
 */

<?php namespace App\Repositories;

use \RuntimeException;
use \InvalidArgumentException;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Str;

class CacheRepository
{
    private $minutes = 10;
    private $key;
    private $enable = true;
    
    public function __construct()
    {
        if (Config::get('app.debug'))
        {
            $this->disable();
        }
    }
    
    public function isEnable()
    {
        return $this->enable;
    }
    
    /**
     * Enable cache
     */
    public function enable()
    {
        $this->enable = true;
    }
    
    /**
     * Disable cache
     */
    public function disable()
    {
        $this->enable = false;
    }
    
    /**
     * Cache expiration
     * 
     * @param integer $minutes
     * @throws InvalidArgumentException
     */
    public function setExpire($minutes=null)
    {
        $minutes = intval($minutes);
        
        if (is_null($minutes) || $minutes<=0)
            throw new InvalidArgumentException('Invalid expiration delay');
        
        $this->minutes = $minutes;
    }
    
    /**
     * Set the current key based on arguments
     * 
     * @param object $object
     * @param string $method
     * @param array $arguments
     * @throws InvalidArgumentException
     */
    public function setKey($object=null, $method=null, $arguments=Array())
    {
        if (is_null($object) || is_null($method))
            throw new InvalidArgumentException('Invalid class/method name');
        
        if (!is_object($object))
            throw new InvalidArgumentException('Invalid class');
        
        if (!is_array($arguments))
            $arguments = Array();
        
        $this->key = Str::slug(str_replace('\\', '-', get_class($object)).' '.$method.' '.implode(' ', $arguments));
        return $this->key;
    }
    
    public function has($key=null)
    {
        if (is_null($key))
            throw new RuntimeException('Wrong cache key');
        
        return (Cache::has($key))?true:false;
    }
    
    public function getByKey($key=null)
    {
        if (is_null($key))
            throw new RuntimeException('Wrong cache key');
        
        if ($this->has($this->key))
        	return Cache::get($this->key);
        
        return null;
    }
    
    public function putByKey($key=null, $data=null)
    {
    	Cache::put($key, $data, $this->minutes);
    }
    
    /**
     * Get the cached values or generate it using the callback
     * 
     * @param Closure $callback
     * @throws RuntimeException
     * @throws InvalidArgumentException
     * @return mixed
     */
    public function get($callback)
    {
        if (is_null($this->key))
            throw new RuntimeException('Wrong cache key');
        
        if (!$this->enable)
        {
            if (!is_callable($callback))
                throw new InvalidArgumentException('The callback must be callable');

            return call_user_func($callback);
        }
        
        if ($this->has($this->key))
            return $this->getByKey($this->key);
            
        if (!is_callable($callback))
            throw new InvalidArgumentException('The callback must be callable');

        $result = call_user_func($callback);
        
        $this->putByKey($this->key, $result);
        
        $this->key = null;
        
        return $result;
    }
    
    /**
     * Flush all the cached item
     */
    public function flush()
    {
        if (!$this->enable)
            return;
        
        Cache::flush();
    }
    
}

Please note that all pasted data is publicly available.