上一篇博客中使用文件實現了緩存組件,這一篇咱們就使用Redis來實現一下,剩下的如何使用memcache、mysql等去實現緩存我就不一一去作了。php
首先咱們須要安裝一下 redis 和 phpredis 庫,phpredis 項目在github上的地址:https://github.com/phpredis/phpredis 。相應的文檔也在上面。mysql
先在 src/cache 文件夾下建立 RedisCache.php 文件。在寫組件的時候發現咱們缺乏一個地方去建立一個 Redis 的實例,而且是在建立 cahce 實例以後,返回給Yii::createObject 方法以前。因此咱們修改了 src/Sf.php 文件,其 createObject 方法的內容以下:git
public static function createObject($name) { $config = require(SF_PATH . "/config/$name.php"); // create instance $instance = new $config['class'](); unset($config['class']); // add attributes foreach ($config as $key => $value) { $instance->$key = $value; } $instance->init(); return $instance; }
對比以前的代碼,不難發現其實只添加了一行 $instance->init();
,這樣咱們就能夠在 init 方法中去建立相應的 Redis 實例,並保存下來。但這樣又會引入一個問題,全部使用 Yii::createObject 建立的實例都必須含有 init 方法(固然你也能夠判斷有沒有這個方法)。那咱們就來實現一個基礎類 Component ,並規定全部使用 Yii::createObject 建立的實例都集成它,而後再在 Component 中加入 init 方法便可。github
爲何選擇這種作法,而不是使用判斷 init 方法存不存在的方式去解決這個問題,主要是考慮到以後可能還須要對這些類作一些公共的事情,就提早抽出了 Component 類。redis
Component 類如今很簡單,其內容以下:sql
<?php namespace sf\base; /** * Component is the base class for most sf classes. * @author Harry Sun <sunguangjun@126.com> */ class Component { /** * Initializes the component. * This method is invoked at the end of the constructor after the object is initialized with the * given configuration. */ public function init() { } }
以後再定義一下 Redis 緩存的配置以下:json
<?php return [ 'class' => 'sf\cache\RedisCache', 'redis' => [ 'host' => 'localhost', 'port' => 6379, 'database' => 0, // 'password' =>'jun', // 'options' => [Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP], ] ];
其中 password 和 options 是選填,其它是必填。緩存
剩下的就是相關實現,就不一一細說了,代碼以下:ide
<?php namespace sf\cache; use Redis; use Exception; use sf\base\Component; /** * CacheInterface * @author Harry Sun <sunguangjun@126.com> */ class RedisCache extends Component implements CacheInterface { /** * @var Redis|array the Redis object or the config of redis */ public $redis; public function init() { if (is_array($this->redis)) { extract($this->redis); $redis = new Redis(); $redis->connect($host, $port); if (!empty($password)) { $redis->auth($password); } $redis->select($database); if (!empty($options)) { call_user_func_array([$redis, 'setOption'], $options); } $this->redis = $redis; } if (!$this->redis instanceof Redis) { throw new Exception('Cache::redis must be either a Redis connection instance.'); } } /** * Builds a normalized cache key from a given key. */ public function buildKey($key) { if (!is_string($key)) { $key = json_encode($key); } return md5($key); } /** * Retrieves a value from cache with a specified key. */ public function get($key) { $key = $this->buildKey($key); return $this->redis->get($key); } /** * Checks whether a specified key exists in the cache. */ public function exists($key) { $key = $this->buildKey($key); return $this->redis->exists($key); } /** * Retrieves multiple values from cache with the specified keys. */ public function mget($keys) { for ($index = 0; $index < count($keys); $index++) { $keys[$index] = $this->buildKey($keys[$index]); } return $this->redis->mGet($keys); } /** * Stores a value identified by a key into cache. */ public function set($key, $value, $duration = 0) { $key = $this->buildKey($key); if ($duration !== 0) { $expire = (int) $duration * 1000; return $this->redis->set($key, $value, $expire); } else { return $this->redis->set($key, $value); } } /** * Stores multiple items in cache. Each item contains a value identified by a key. */ public function mset($items, $duration = 0) { $failedKeys = []; foreach ($items as $key => $value) { if ($this->set($key, $value, $duration) === false) { $failedKeys[] = $key; } } return $failedKeys; } /** * Stores a value identified by a key into cache if the cache does not contain this key. */ public function add($key, $value, $duration = 0) { if (!$this->exists($key)) { return $this->set($key, $value, $duration); } else { return false; } } /** * Stores multiple items in cache. Each item contains a value identified by a key. */ public function madd($items, $duration = 0) { $failedKeys = []; foreach ($items as $key => $value) { if ($this->add($key, $value, $duration) === false) { $failedKeys[] = $key; } } return $failedKeys; } /** * Deletes a value with the specified key from cache */ public function delete($key) { $key = $this->buildKey($key); return $this->redis->delete($key); } /** * Deletes all values from cache. */ public function flush() { return $this->redis->flushDb(); } }
訪問 http://localhost/simple-framework/public/index.php?r=site/cache 路徑,獲得結果以下:測試
我就是測試一下緩存組件
這樣咱們完成了使用 Redis 的緩存組件。
好了,今天就先到這裏。項目內容和博客內容也都會放到Github上,歡迎你們提建議。
code:https://github.com/CraryPrimitiveMan/simple-framework/tree/1.0
blog project:https://github.com/CraryPrimitiveMan/create-your-own-php-framework