Home  >  Q&A  >  body text

Create different keys for query cache in Laravel

I'm using a repository in a project to cache all queries.

There is a BaseRepository.

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;

class BaseRepository implements BaseRepositoryInterface{
    protected $model;
    protected int $cacheDuration = 600; //per seconds
    public function __construct(Model $model)
    {
        return $this->model = $model;
    }

    public function paginate(int $paginate,string $cacheKey)
    {
        return Cache::remember($cacheKey,$this->cacheDuration , function () use ($paginate) {
            return $this->model->latest()->paginate($paginate);
        });
    }
    // other methods ...
}

Then I used this repository in my service

Postal Service:

use Illuminate\Support\Facades\App;

class PostService{
    public PostRepositoryInterface $postRepository;

    public function __construct()
    {
        $this->postRepository = App::make(PostRepositoryInterface::class);
    }
    public function paginate(int $paginate, string $cacheKey)
    {
        return $this->postRepository->paginate($paginate,$cacheKey);
    }
}

Finally I used PostService

in the controller

Rear Controller:

class PostController extends Controller{

    public PostService $postService;
    public function __construct()
    {
        $this->postService = App::make(PostService::class);
    }

    public function index()
    {
        string $cacheKey = "posts.paginate";
        return $this->postService->paginate(10);
    }
}

index method will correctly return the first 10 latest records. Now I need to create a unique CacheKey for all repository queries. For example

TableName concat FunctionName // posts.paginate

So I can use this code in all methods of the repository

public function paginate(int $paginate)
{
    $cacheKey = $this->model->getTable().__FUNCTION__;
    return Cache::remember($cacheKey,$this->cacheDuration , function () use ($paginate) {
        return $this->model->latest()->paginate($paginate);
    });
}

This is good. But the problem is that this code is repeated in all methods of the class. If I use this code in another class, the method name will be incorrect. Do you have any suggestions to prevent duplication of this code?

P粉739886290P粉739886290237 days ago411

reply all(2)I'll reply

  • P粉401901266

    P粉4019012662024-03-20 15:30:59

    I solved this problem by passing the function name to another class

    I created the CacheKey class:

    class CacheKey{
    
        public static function generate(Model $model, $functionName):string
        {
            return $model->getTable()."_".$functionName;
        }
    }

    Then in any method of the repository we can use this helper class like this:

    $cacheKey = CacheKey::generate($this->model,__FUNCTION__);

    reply
    0
  • P粉287726308

    P粉2877263082024-03-20 15:11:01

    You can easily use magic methods this way:

    class CacheService {
        private const $cacheableMethods = ['paginate'];
        private $otherSerivce;
        public __construct($otherSerivce) {
           $this->otherSerivce = $otherSerivce;
        }
    
        public __get($method, $args) {
            if(!in_array($method, static::$cachableMethods)) {
              return $this->otherSerivce->{$method}(...$args);
            }
    
            return Cache::remember(implode([$method, ...$args], ':'), function () {
                return $this->otherSerivce->{$method}(...$args);
            });
        }
    
    }
    

    reply
    0
  • Cancelreply