在 thinkphp 之前的版本中,一般是使用如下形式使用 Cache 功能:
public function getSomeData($options) {
$key = md5(serialize($options));
$cached = Cache::get($key);
if($cached === false) {
$cached = M('Model')->where($conditions)->select();
Cache:set($key, $cached);
}
return $cached;
}这样的方法在任何我们想使用缓存的时候都要重复实现一遍,这实在令人郁闷。而现在,php 中提供了 trait 新特性可以实现类似 python 的 decorator 或者 Java 的 annotation 功能。这就允许我们将整个 cache 的动作封装起来,降低代码量,极大的提升开发效率。代码如下:
<?php
namespace app\common\traits;
use think\Cache;
trait Cached
{
public function __call($name, $args)
{
if(substr($name, 0, 6) === 'cached') {
$method = substr($name, 6);
if(method_exists($this, $method)) {
$id = get_class($this) . '::' . $method . '_' . md5(serialize($args));
$cached = Cache::get($id);
if($cached === false) {
$cached = call_user_func_array([$this, $method], $args);
Cache::set($id, $cached);
}
return $cached;
}
}
return parent::__call($name, $args);
}
}使用样例:<?php
# Model 类
namespace app\common\model;
use app\common\traits\Cached;
class Org
{
use Cached;
protected $data = [1,2,3,4];
public function lists() {
return $this->data;
}
public function add() {
$this->data[] = 5;
}
}<?php
# Controller 类
namespace app\index\controller;
use app\common\model\Org;
class Index
{
public function index() {
$org = new Org;
dump($org->lists());
dump($org->cachedLists());
$org->add();
dump($org->lists());
dump($org->cachedLists());
}
}通过调用 'cached' + 原方法 的方式既可以读取/设置缓存。tp5 提供了 db query 的缓存功能,但是其他地方设置缓存还是不太方便,同时 db query 的缓存功能和数据操作过于紧密,利用 trait 进行缓存可以将缓存操作置后,同时也保持无缓存的函数存在,方便程序控制。
更进一步,可以在 trait 里增加一些 cache option 的控制,实现类似于 $org->cacheOption('expire',60)->cachedLists() 动态设置缓存过期时间等。
