使用Laravel中的用户过滤器缓存数据(而不仅仅是)

时间:2018-03-23 23:29:24

标签: php laravel caching

Laravel 5.5 + Redis。

在控制器中获得以下代码:

$products = Cache::remember('category_'.$category->alias.'_page_'.$page, 1440, function() use ($childrenCategoriesIndexes){
  return Product::whereIn('category_id', $childrenCategoriesIndexes)
                        ->userFilter()
                        ->paginate(15);
});

它缓存每个页面。但是,如果有太多的自定义过滤器呢?这是来自scopeUserFilter()模型的Product

public function scopeUserFilter($query) {
        if (request('price_from')) {
            $query->where('price', '>', request('price_from'));
        }
        if (request('price_to')) {
            $query->where('price', '<', request('price_to'));
        }
        return $query;
    }

而且只有2个变量。但是,如果有10个以上的变量,如何缓存这些数据怎么办?我认为像这样的钥匙不好:

'category_'.$category->alias.'_page_'.$page.'_'.request('price_from').'_'.request('price_to')

3 个答案:

答案 0 :(得分:3)

将参数括起来,然后你可以尽可能多地包括:

$params = [
    'page' => 1,
    'price_from' => '',
    'price_to' => '',
    'param0' => '',
    ...
];
foreach (array_keys($params) as $param) {
    if (request()->has($param))
        $params[$param] = request()->input($param);
}
$prefix = 'category_';
$hashed = md5(json_encode($params));
$cache_key = $prefix . $hashed;

答案 1 :(得分:2)

代替:

  • 定义所有可能参数的数组
  • 遍历该数组以检查请求是否包含这些参数中的任何一个,如果包含,则将该值分配给数组中的相关键
  • 创建数组的哈希以用作缓存的键

...(我是从this article中学到的)一种替代方法,并且可能更灵活:

  • 创建所有请求参数的数组并按字母顺序对其进行排序
  • 使用此排序数组重建网址
  • 为此网址创建一个哈希,以用作缓存的键

这意味着您的代码将如下所示:

$url = request()->url();
$queryParams = request()->query();

ksort($queryParams);

$queryString = http_build_query($queryParams);

$fullUrl = "{$url}?{$queryString}";

$rememberKey = sha1($fullUrl);

return Cache::remember($rememberKey, $minutes, function () use ($data) {
    return $data;
});

答案 2 :(得分:1)

虽然@Ben的答案确实解决了我们如何缓存多个参数,但是缓存所有请求并不是一个好习惯。

缓存通常用于最常用的请求(高频率读取,不频繁写入)。例如,缓存前10个参数组合。如果你开始缓存长尾,你就会失去缓存的目的,因为你会更频繁地写入更频繁的写入和更少的读取。如果您使用内存缓存引擎,最终会耗尽内存

我建议您重新考虑一下您的缓存策略