laravel 5.4 访问器使用缓存的坑

原创 Laravel
阅读数: 1301 2019年06月24日

Laravel 5.4 的 Eloquent 有个访问器功能,非常好用。

今天有个缓存需求,商品的库存 num 需要单独 redis 缓存记录(cache_num_{id}),应对并发下单,而不是直接查询数据库。且操作中一直更新这个独立缓存值,保证这个值最准确。

而且这件商品又给缓存了24小时(cache_product_{id})。

之前取商品数量的时候,需要单独去调用这个商品的对于库存缓存 cache_num_{id},比较麻烦。

想直接通过商品模型里面取出商品库存的时候,调用的是单独缓存(cache_num_{id})。


然后使用了访问器:

public function getNumAttribute($value)
{
   $result = Cache::get('cache_num_'.$this->id); //先从缓存获取
   if($result) return $result; //存在,返回独立缓存值(cache_num_{id})   
   return $value; //如果空值,就返回原值(原值来自 cache_product_{id} 的缓存)
}


问题来了:当 num = 0 的时候,会被认为成空值,直接返回 $value 也就是主体缓存的值,此时的值并不是0。

想到错误的解决方法:

public function getNumAttribute($value)
{
   $result = Cache::get('cache_num_'.$this->id); //先从缓存获取
   if($result) return $result; //存在,返回独立缓存值(cache_num_{id})   
   return $this->where('id','=', $this->id)->value('num'); //重新查询数据库(造成死循环)
}

一直拿不到数据库最新的数据。

郁闷了1天,才明白:调用num的时候,自动会调用 getNumAttribute()方法,会死循环。

如果调用原值就不会触发访问器,正解:

public function getNumAttribute($value)
{
   $result = Cache::get('cache_num_'.$this->id); //先从缓存获取
   if($result) return $result; //存在,返回独立缓存值(cache_num_{id})
   //重新查询
   $model = $this->find($this->id);
   $numLeft = $model->getOriginal('num'); //取原值,避免调用自己
   return $numLeft ; //返回数据库最新的数据
}


phpriji.cn | 网站地图 | 沪ICP备17015433号-1