Home > Enterprise >  how to create a unique key for caching query in laravel
how to create a unique key for caching query in laravel

Time:04-17

I used repository in a project that caching all queries.

there's 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

PostService:

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 using the PostService in my controller

PostController:

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

the index method will return top 10 latest record correctly. 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 into all method of 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 fine. but the problem is that this code repeat in all the method of this class. if i use this code in another class, method name's will be incorrect. What do you suggest to prevent duplication of this code?

CodePudding user response:

i solve this problem by passing function name to another class

i created CacheKey class:

class CacheKey{

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

}

Then in any method of repository we can use this helper class as follows:

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

CodePudding user response:

you can easily use magic method in 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);
        });
    }

}
  • Related