Мне нужно было продлить Illuminate\Database\Eloquent\Model
и Illuminate\Database\Eloquent\Builder
.
Мой расширенный класс Builder
<?php
namespace App\Laravel\Database\Eloquent;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Facades\Cache;
/**
* @mixin \Illuminate\Database\Query\Builder
*/
class CachedBuilder extends Builder
{
const CACHE_THRESHOLD = 10000;
const CACHE_DURATION = 60;
const CACHE_KEY_PREFIX = 'pagination_';
/**
* Paginate the given query.
*
* @param int $perPage
* @param array $columns
* @param string $pageName
* @param int|null $page
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
*
* @throws \InvalidArgumentException
*/
public function paginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null)
{
$page = $page ?: Paginator::resolveCurrentPage($pageName);
$perPage = $perPage ?: $this->model->getPerPage();
$key = self::CACHE_KEY_PREFIX . '_' . $this->getModel()->getTable();
$total = Cache::get($key);
if(!$total) {
$total = $this->toBase()->getCountForPagination();
if($total > self::CACHE_THRESHOLD) {
Cache::put($key, $total, self::CACHE_DURATION);
}
}
$results = $total ? $this->forPage($page, $perPage)->get($columns)
: $this->model->newCollection();
return $this->paginator($results, $total, $perPage, $page, [
'path' => Paginator::resolveCurrentPath(),
'pageName' => $pageName,
]);
}
}
Мой расширенный класс модели
<?php
namespace App\Laravel\Database\Eloquent;
use Illuminate\Database\Eloquent\Model;
abstract class CachedModel extends Model
{
/**
* @param \Illuminate\Database\Query\Builder $query
* @return CachedBuilder|\Illuminate\Database\Eloquent\Builder|static
*/
public function newEloquentBuilder($query)
{
return new CachedBuilder($query);
}
}
И теперь мне просто нужно расширить любую из моих моделей с помощью этого нового класса CachedModel, чтобы применить кеширование результатов общего подсчета.