构建自己的PHP框架--构建缓存组件(2)
上一篇博客中使用文件实现了缓存组件,这一篇我们就使用Redis来实现一下,剩下的如何使用memcache、mysql等去实现缓存我就不一一去做了。
首先我们需要安装一下 redis 和 phpredis 库,phpredis 项目在github上的地址:https://github.com/phpredis/phpredis 。相应的文档也在上面。
先在 src/cache 文件夹下创建 RedisCache.php 文件。在写组件的时候发现我们缺少一个地方去创建一个 Redis 的实例,并且是在创建 cahce 实例之后,返回给Yii::createObject 方法之前。所以我们修改了 src/Sf.php 文件,其 createObject 方法的内容如下:
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 方法即可。
为什么选择这种做法,而不是使用判断 init 方法存不存在的方式去解决这个问题,主要是考虑到之后可能还需要对这些类做一些公共的事情,就提前抽出了 Component 类。
Component 类现在很简单,其内容如下:
<?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 缓存的配置如下:
<?php
return [
'class' => 'sf\cache\RedisCache',
'redis' => [
'host' => 'localhost',
'port' => 6379,
'database' => 0,
// 'password' =>'jun',
// 'options' => [Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP],
]
];
其中 password 和 options 是选填,其它是必填。
剩下的就是相关实现,就不一一细说了,代码如下:
<?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
构建自己的PHP框架--构建缓存组件(2)的更多相关文章
- 构建自己的PHP框架--构建缓存组件(1)
作为一个框架,我们还没有相应的缓存组件,下面我们就来构建我们的缓存组件. 先来定义一下接口,在 src 文件夹下创建 cache 文件夹,在cache文件夹下创建 CacheInterface.php ...
- 构建自己的PHP框架--构建模版引擎(1)
前段时间太忙,导致好久都没有更新博客了,今天抽出点时间来写一篇. 其实这个系列的博客很久没有更新了,之前想好好规划一下,再继续写,然后就放下了,今天再捡起来继续更新. 今天我们来说一下,如何构建自己的 ...
- 构建自己的PHP框架--构建模版引擎(3)
之前我们实现了最简单的echo命令的模版替换,就是将{{ $name }}这样一段内容替换成<?php echo $name ?>. 现在我们来说下其他的命令,先来回顾下之前的定义 输出变 ...
- 构建自己的PHP框架--构建模版引擎(2)
自从来到新公司就一直很忙,最近这段时间终于稍微闲了一点,赶紧接着写这个系列,感觉再不写就烂尾了. 之前我们说到,拿到{{ $name }}这样一段内容时,我们只需要将它转化成<?php echo ...
- 基于Dubbo框架构建分布式服务(一)
Dubbo是Alibaba开源的分布式服务框架,我们可以非常容易地通过Dubbo来构建分布式服务,并根据自己实际业务应用场景来选择合适的集群容错模式,这个对于很多应用都是迫切希望的,只需要通过简单的配 ...
- 基于Dubbo框架构建分布式服务
Dubbo是Alibaba开源的分布式服务框架,我们可以非常容易地通过Dubbo来构建分布式服务,并根据自己实际业务应用场景来选择合适的集群容错模式,这个对于很多应用都是迫切希望的,只需要通过简单的配 ...
- [转载] 基于Dubbo框架构建分布式服务
转载自http://shiyanjun.cn/archives/1075.html Dubbo是Alibaba开源的分布式服务框架,我们可以非常容易地通过Dubbo来构建分布式服务,并根据自己实际业务 ...
- 教你构建好 SpringBoot + SSM 框架
来源:Howie_Y https://juejin.im/post/5b53f677f265da0f8f203914 目前最主流的 java web 框架应该是 SSM,而 SSM 框架由于更轻便与灵 ...
- 教你十分钟构建好 SpringBoot + SSM 框架
目前最主流的 java web 框架应该是 SSM,而 SSM 框架由于更轻便与灵活目前受到了许多人的青睐.而 SpringBoot 的轻量化,简化项目配置, 没有 XML 配置要求等优点现在也得到了 ...
随机推荐
- ubuntu 16.04 安装完QQ后,更新或apt-get报错
apt-get install python-pip正在读取软件包列表... 完成正在分析软件包的依赖关系树 正在读取状态信息... 完成 您可能需要运行“apt-get -f install”来纠正 ...
- 李洪强经典面试题152-Runtime
李洪强经典面试题152-Runtime Runtime Runtime是什么 Runtime 又叫运行时,是一套底层的 C 语言 API,其为 iOS 内部的核心之一,我们平时编写的 OC 代码, ...
- Struts2登录小例子
前面实现了一个数据显示的例子,下面我来实现以下使用Struts2登录 首先是配置不用过多解释 注意名字要和类名保持一致 因为实现的是action这个方法所以需要用action.log来跳转到类里面 解 ...
- C#3.0扩展方法学习篇
什么是类的扩展方法 扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型. MSDN Extension methods enable you to &q ...
- 报文解析及CRC类
/// <summary> /// 报文解析转换类 /// </summary> public class DatagramConvert { public static En ...
- 使用libjpeg.framework压缩UIImage
+(void)writeFile:(NSString *)filePath withQuality:(int)quality { //初始化图片参数 UIImage *image=[UIImage i ...
- C++11 并发指南七(C++11 内存模型一:介绍)
第六章主要介绍了 C++11 中的原子类型及其相关的API,原子类型的大多数 API 都需要程序员提供一个 std::memory_order(可译为内存序,访存顺序) 的枚举类型值作为参数,比如:a ...
- clojure基础入门(一)
最近在看storm的源码,就学习分享下clojure语法. 阅读目录: 概述 变量 运算符 流程控制 总结 概述 clojure是一种运行在JVM上的Lisp方言,属于函数式编程范式,它和java可以 ...
- ASP.NET MVC学前篇之请求流程
ASP.NET MVC学前篇之请求流程 请求流程描述 对于请求的流程,文章的重点是讲HttpApplication和HttpModule之间的关系,以及一个简单的示例实现.(HttpModule又是M ...
- Azure PowerShell (9) 使用PowerShell导出订阅下所有的Azure VM的Public IP和Private IP
<Windows Azure Platform 系列文章目录> 笔者在之前的工作中,有客户提出想一次性查看Azure订阅下的所有Azure VM的Public IP和Private IP. ...