关于 Laravel ORM 对 Model::find 方法进行缓存

前段时间作项目时候,想要在不改变方法签名的状况下,给 Model::find 方法作个缓存。并且想要作到即插即用。node

1.先看一下当咱们调用 find 方法时,框架干了什么?json

找到 Illuminate\Database\Eloquent\Model 的代码,搜索 find,没有该方法。看来是走了 __callStatic 这个魔术方法。该方法里只有一行代码:缓存

return (new static)->$method(...$parameters);

  

static 指的是调用该静态方法的类(若是使用的是 UserModel::find(1),则 static 就表明 UserModel 类)。看来是实例化了一个对象,并调用了成员方法。架构

2.分析如何优雅地在中间插一脚框架

为了可以在调用 find 时候,先走咱们的缓存,因此咱们须要覆盖 __callStatic 方法,并检测若是是 find 方法,则优先返回缓存中的数据。this

另外,为了可以达到即插即用的效果,咱们使用继承的方式,而是使用了 Trait。核心逻辑以下:spa

public static function create($data = null){
 if ($data == null){
 return null;
 }
 $instance = new static;
 foreach ($data as $key => $value){
 $instance[$key] = $value;
 }
 return $instance;
}
/**
 * 若是方法是 find($id, $nocache)
 *
 * @param  string  $method
 * @param  array  $parameters
 * @return mixed
 */
public static function __callStatic($method, $parameters)
{
 if ($method == 'find'){
 // 从缓存中获取数据
 $obj = static::create(json_decode(Redis::get(static::getCacheKey($parameters[0])), true));
 if (null == $obj){
 $obj = (new static)->$method(...$parameters);
 if (null == $obj){
 return null;
 } else {
 $key = static::getCacheKey($parameters[0]);
 // 设置缓存及过时时间
 Redis::set($key, $obj);
 Redis::expire($key, static::$expire_time);
 return $obj;
 }
 } else {
 $obj->exists = true;
 return $obj;
 }
 } else if($method == 'findNoCache'){
 $method = 'find';
 return (new static)->$method(...$parameters);
 }
 return (new static)->$method(...$parameters);
}
private static function getCacheKey($id){
 $name = str_replace('\\', ':', __CLASS__);
 return "{$name}:{$id}";
}

  

大致逻辑上面已经介绍过了:覆盖 __callStatic 方法,判断若是是调用 find ,则走缓存(无缓存,查询后须要设置缓存)。另新增 findNoCache 方法。code

3.细节补充对象

当修改(或删除)数据(调用 save 方法)时须要删除已缓存的内容。blog

private static function clearCache($id){
 Redis::del(self::getCacheKey($id));
}
/**
 * when save, should clear cache
 * @param array $options
 */
public function save(array $options = []){
 static::clearCache($this[$this->primaryKey]);
 return parent::save($options);
}
// delete 方法我暂时写,内容相似 save 方法
如何使用。在须要使用 find 缓存的 Model 类里,加上一行就够了。
class User extends BaseModel
{
 use MemoryCacheTrait;
}

  

快去试试吧。

更多PHP内容请访问:

腾讯T3-T4标准精品PHP架构师教程目录大全,只要你看完保证薪资上升一个台阶(持续更新)

相关文章
相关标签/搜索