diff --git a/app/Repositories/AircraftRepository.php b/app/Repositories/AircraftRepository.php index 51156961..d8025c09 100644 --- a/app/Repositories/AircraftRepository.php +++ b/app/Repositories/AircraftRepository.php @@ -3,8 +3,8 @@ namespace App\Repositories; use App\Models\Aircraft; +use App\Repositories\Traits\CacheableRepository; use Prettus\Repository\Contracts\CacheableInterface; -use Prettus\Repository\Traits\CacheableRepository; class AircraftRepository extends BaseRepository implements CacheableInterface { diff --git a/app/Repositories/AirlineRepository.php b/app/Repositories/AirlineRepository.php index 65d52eb0..f073287b 100644 --- a/app/Repositories/AirlineRepository.php +++ b/app/Repositories/AirlineRepository.php @@ -3,8 +3,8 @@ namespace App\Repositories; use App\Models\Airline; +use App\Repositories\Traits\CacheableRepository; use Prettus\Repository\Contracts\CacheableInterface; -use Prettus\Repository\Traits\CacheableRepository; class AirlineRepository extends BaseRepository implements CacheableInterface diff --git a/app/Repositories/AirportRepository.php b/app/Repositories/AirportRepository.php index 946f6881..1c44f89c 100644 --- a/app/Repositories/AirportRepository.php +++ b/app/Repositories/AirportRepository.php @@ -3,8 +3,8 @@ namespace App\Repositories; use App\Models\Airport; +use App\Repositories\Traits\CacheableRepository; use Prettus\Repository\Contracts\CacheableInterface; -use Prettus\Repository\Traits\CacheableRepository; class AirportRepository extends BaseRepository implements CacheableInterface diff --git a/app/Repositories/FareRepository.php b/app/Repositories/FareRepository.php index 71c0b56a..3a42d3ad 100644 --- a/app/Repositories/FareRepository.php +++ b/app/Repositories/FareRepository.php @@ -3,8 +3,8 @@ namespace App\Repositories; use App\Models\Fare; +use App\Repositories\Traits\CacheableRepository; use Prettus\Repository\Contracts\CacheableInterface; -use Prettus\Repository\Traits\CacheableRepository; class FareRepository extends BaseRepository implements CacheableInterface { diff --git a/app/Repositories/FlightRepository.php b/app/Repositories/FlightRepository.php index 6cdce8cf..10d3b884 100644 --- a/app/Repositories/FlightRepository.php +++ b/app/Repositories/FlightRepository.php @@ -4,10 +4,10 @@ namespace App\Repositories; use App\Models\Flight; use App\Repositories\Criteria\WhereCriteria; +use App\Repositories\Traits\CacheableRepository; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Http\Request; use Prettus\Repository\Contracts\CacheableInterface; -use Prettus\Repository\Traits\CacheableRepository; class FlightRepository extends BaseRepository implements CacheableInterface { diff --git a/app/Repositories/PirepRepository.php b/app/Repositories/PirepRepository.php index 5df420f3..58781300 100644 --- a/app/Repositories/PirepRepository.php +++ b/app/Repositories/PirepRepository.php @@ -4,8 +4,8 @@ namespace App\Repositories; use App\Models\Pirep; use App\Models\User; +use App\Repositories\Traits\CacheableRepository; use Prettus\Repository\Contracts\CacheableInterface; -use Prettus\Repository\Traits\CacheableRepository; class PirepRepository extends BaseRepository implements CacheableInterface { diff --git a/app/Repositories/RankRepository.php b/app/Repositories/RankRepository.php index bfbac8a0..323546a8 100644 --- a/app/Repositories/RankRepository.php +++ b/app/Repositories/RankRepository.php @@ -3,8 +3,8 @@ namespace App\Repositories; use App\Models\Rank; +use App\Repositories\Traits\CacheableRepository; use Prettus\Repository\Contracts\CacheableInterface; -use Prettus\Repository\Traits\CacheableRepository; class RankRepository extends BaseRepository implements CacheableInterface { diff --git a/app/Repositories/SubfleetRepository.php b/app/Repositories/SubfleetRepository.php index 178268a4..08dcbd6b 100644 --- a/app/Repositories/SubfleetRepository.php +++ b/app/Repositories/SubfleetRepository.php @@ -3,8 +3,8 @@ namespace App\Repositories; use App\Models\Subfleet; +use App\Repositories\Traits\CacheableRepository; use Prettus\Repository\Contracts\CacheableInterface; -use Prettus\Repository\Traits\CacheableRepository; class SubfleetRepository extends BaseRepository implements CacheableInterface { diff --git a/app/Repositories/Traits/CacheableRepository.php b/app/Repositories/Traits/CacheableRepository.php new file mode 100644 index 00000000..2b8a5c8a --- /dev/null +++ b/app/Repositories/Traits/CacheableRepository.php @@ -0,0 +1,341 @@ +cacheRepository = $repository; + + return $this; + } + + /** + * Return instance of Cache Repository + * + * @return CacheRepository + */ + public function getCacheRepository() + { + if (is_null($this->cacheRepository)) { + $this->cacheRepository = app(config('repository.cache.repository', 'cache')); + } + + return $this->cacheRepository; + } + + /** + * Skip Cache + * + * @param bool $status + * + * @return $this + */ + public function skipCache($status = true) + { + $this->cacheSkip = $status; + + return $this; + } + + /** + * @return bool + */ + public function isSkippedCache() + { + $skipped = isset($this->cacheSkip) ? $this->cacheSkip : false; + $request = app('Illuminate\Http\Request'); + $skipCacheParam = config('repository.cache.params.skipCache', 'skipCache'); + + if ($request->has($skipCacheParam) && $request->get($skipCacheParam)) { + $skipped = true; + } + + return $skipped; + } + + /** + * @param $method + * + * @return bool + */ + protected function allowedCache($method) + { + $cacheEnabled = config('repository.cache.enabled', true); + + if (!$cacheEnabled) { + return false; + } + + $cacheOnly = isset($this->cacheOnly) ? $this->cacheOnly : config('repository.cache.allowed.only', null); + $cacheExcept = isset($this->cacheExcept) ? $this->cacheExcept : config('repository.cache.allowed.except', null); + + if (is_array($cacheOnly)) { + return in_array($method, $cacheOnly); + } + + if (is_array($cacheExcept)) { + return !in_array($method, $cacheExcept); + } + + if (is_null($cacheOnly) && is_null($cacheExcept)) { + return true; + } + + return false; + } + + /** + * Get Cache key for the method + * + * @param $method + * @param $args + * + * @return string + */ + public function getCacheKey($method, $args = null) + { + + $request = app('Illuminate\Http\Request'); + $args = serialize($args); + $criteria = $this->serializeCriteria(); + $key = sprintf('%s@%s-%s', get_called_class(), $method, md5($args . $criteria . $request->fullUrl())); + + CacheKeys::putKey(get_called_class(), $key); + + return $key; + + } + + /** + * Serialize the criteria making sure the Closures are taken care of. + * + * @return string + */ + protected function serializeCriteria() + { + try { + return serialize($this->getCriteria()); + } catch (Exception $e) { + return serialize($this->getCriteria()->map(function ($criterion) { + return $this->serializeCriterion($criterion); + })); + } + } + + /** + * Serialize single criterion with customized serialization of Closures. + * + * @param \Prettus\Repository\Contracts\CriteriaInterface $criterion + * @return \Prettus\Repository\Contracts\CriteriaInterface|array + * + * @throws \Exception + */ + protected function serializeCriterion($criterion) + { + try { + serialize($criterion); + + return $criterion; + } catch (Exception $e) { + // We want to take care of the closure serialization errors, + // other than that we will simply re-throw the exception. + if ($e->getMessage() !== "Serialization of 'Closure' is not allowed") { + throw $e; + } + + $r = new ReflectionObject($criterion); + + return [ + 'hash' => md5((string)$r), + 'properties' => $r->getProperties(), + ]; + } + } + + /** + * Get cache minutes + * + * @return int + */ + public function getCacheMinutes() + { + $cacheMinutes = isset($this->cacheMinutes) ? $this->cacheMinutes : config('repository.cache.minutes', 30); + + return $cacheMinutes; + } + + /** + * Retrieve all data of repository + * + * @param array $columns + * + * @return mixed + */ + public function all($columns = ['*']) + { + if (!$this->allowedCache('all') || $this->isSkippedCache()) { + return parent::all($columns); + } + + $key = $this->getCacheKey('all', func_get_args()); + $minutes = $this->getCacheMinutes(); + $value = $this->getCacheRepository()->remember($key, $minutes, function () use ($columns) { + return parent::all($columns); + }); + + $this->resetModel(); + $this->resetScope(); + return $value; + } + + /** + * Retrieve all data of repository, paginated + * + * @param null $limit + * @param array $columns + * + * @return mixed + */ + public function paginate($limit = null, $columns = ['*'], $method='paginate') + { + if (!$this->allowedCache('paginate') || $this->isSkippedCache()) { + return parent::paginate($limit, $columns); + } + + $key = $this->getCacheKey('paginate', func_get_args()); + + $minutes = $this->getCacheMinutes(); + $value = $this->getCacheRepository()->remember($key, $minutes, function () use ($limit, $columns) { + return parent::paginate($limit, $columns); + }); + + $this->resetModel(); + $this->resetScope(); + return $value; + } + + /** + * Find data by id + * + * @param $id + * @param array $columns + * + * @return mixed + */ + public function find($id, $columns = ['*']) + { + if (!$this->allowedCache('find') || $this->isSkippedCache()) { + return parent::find($id, $columns); + } + + $key = $this->getCacheKey('find', func_get_args()); + $minutes = $this->getCacheMinutes(); + $value = $this->getCacheRepository()->remember($key, $minutes, function () use ($id, $columns) { + return parent::find($id, $columns); + }); + + $this->resetModel(); + $this->resetScope(); + return $value; + } + + /** + * Find data by field and value + * + * @param $field + * @param $value + * @param array $columns + * + * @return mixed + */ + public function findByField($field, $value = null, $columns = ['*']) + { + if (!$this->allowedCache('findByField') || $this->isSkippedCache()) { + return parent::findByField($field, $value, $columns); + } + + $key = $this->getCacheKey('findByField', func_get_args()); + $minutes = $this->getCacheMinutes(); + $value = $this->getCacheRepository()->remember($key, $minutes, function () use ($field, $value, $columns) { + return parent::findByField($field, $value, $columns); + }); + + $this->resetModel(); + $this->resetScope(); + return $value; + } + + /** + * Find data by multiple fields + * + * @param array $where + * @param array $columns + * + * @return mixed + */ + public function findWhere(array $where, $columns = ['*']) + { + if (!$this->allowedCache('findWhere') || $this->isSkippedCache()) { + return parent::findWhere($where, $columns); + } + + $key = $this->getCacheKey('findWhere', func_get_args()); + $minutes = $this->getCacheMinutes(); + $value = $this->getCacheRepository()->remember($key, $minutes, function () use ($where, $columns) { + return parent::findWhere($where, $columns); + }); + + $this->resetModel(); + $this->resetScope(); + return $value; + } + + /** + * Find data by Criteria + * + * @param CriteriaInterface $criteria + * + * @return mixed + */ + public function getByCriteria(CriteriaInterface $criteria) + { + if (!$this->allowedCache('getByCriteria') || $this->isSkippedCache()) { + return parent::getByCriteria($criteria); + } + + $key = $this->getCacheKey('getByCriteria', func_get_args()); + $minutes = $this->getCacheMinutes(); + $value = $this->getCacheRepository()->remember($key, $minutes, function () use ($criteria) { + return parent::getByCriteria($criteria); + }); + + $this->resetModel(); + $this->resetScope(); + return $value; + } +} diff --git a/app/Repositories/UserRepository.php b/app/Repositories/UserRepository.php index f2ffd41c..4b3d53a0 100644 --- a/app/Repositories/UserRepository.php +++ b/app/Repositories/UserRepository.php @@ -2,8 +2,8 @@ namespace App\Repositories; use App\Models\User; +use App\Repositories\Traits\CacheableRepository; use Prettus\Repository\Contracts\CacheableInterface; -use Prettus\Repository\Traits\CacheableRepository; class UserRepository extends BaseRepository implements CacheableInterface {