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();
}
}