上一篇博客中使用文件实现了缓存组件,这一篇我们就使用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)的更多相关文章

  1. 构建自己的PHP框架--构建缓存组件(1)

    作为一个框架,我们还没有相应的缓存组件,下面我们就来构建我们的缓存组件. 先来定义一下接口,在 src 文件夹下创建 cache 文件夹,在cache文件夹下创建 CacheInterface.php ...

  2. 构建自己的PHP框架--构建模版引擎(1)

    前段时间太忙,导致好久都没有更新博客了,今天抽出点时间来写一篇. 其实这个系列的博客很久没有更新了,之前想好好规划一下,再继续写,然后就放下了,今天再捡起来继续更新. 今天我们来说一下,如何构建自己的 ...

  3. 构建自己的PHP框架--构建模版引擎(3)

    之前我们实现了最简单的echo命令的模版替换,就是将{{ $name }}这样一段内容替换成<?php echo $name ?>. 现在我们来说下其他的命令,先来回顾下之前的定义 输出变 ...

  4. 构建自己的PHP框架--构建模版引擎(2)

    自从来到新公司就一直很忙,最近这段时间终于稍微闲了一点,赶紧接着写这个系列,感觉再不写就烂尾了. 之前我们说到,拿到{{ $name }}这样一段内容时,我们只需要将它转化成<?php echo ...

  5. 基于Dubbo框架构建分布式服务(一)

    Dubbo是Alibaba开源的分布式服务框架,我们可以非常容易地通过Dubbo来构建分布式服务,并根据自己实际业务应用场景来选择合适的集群容错模式,这个对于很多应用都是迫切希望的,只需要通过简单的配 ...

  6. 基于Dubbo框架构建分布式服务

    Dubbo是Alibaba开源的分布式服务框架,我们可以非常容易地通过Dubbo来构建分布式服务,并根据自己实际业务应用场景来选择合适的集群容错模式,这个对于很多应用都是迫切希望的,只需要通过简单的配 ...

  7. [转载] 基于Dubbo框架构建分布式服务

    转载自http://shiyanjun.cn/archives/1075.html Dubbo是Alibaba开源的分布式服务框架,我们可以非常容易地通过Dubbo来构建分布式服务,并根据自己实际业务 ...

  8. 教你构建好 SpringBoot + SSM 框架

    来源:Howie_Y https://juejin.im/post/5b53f677f265da0f8f203914 目前最主流的 java web 框架应该是 SSM,而 SSM 框架由于更轻便与灵 ...

  9. 教你十分钟构建好 SpringBoot + SSM 框架

    目前最主流的 java web 框架应该是 SSM,而 SSM 框架由于更轻便与灵活目前受到了许多人的青睐.而 SpringBoot 的轻量化,简化项目配置, 没有 XML 配置要求等优点现在也得到了 ...

随机推荐

  1. 关于learntorank http://qiita.com/rockhopper/items/bb3d46f01df5f6499123

    一.数据转换 如何对于训练数据做pairwise的transform,比如你原始数据是要么点击要么不点击,如何对这些样本数据做pairwise的transform? 下面的方法主要是做组合的方法,就是 ...

  2. oracle 全文检索创建脚本示例

    --创建全文索引 grant execute on ctx_ddl to username;--使用其他帐号对username授权exec ctx_ddl.create_preference('my_ ...

  3. JQuery之$.ajaxPOST数据

    function postSimpleData() { $.ajax({ type: "POST", url: "/Service/SimpleData", c ...

  4. CSS 基础语法

    注:CSS对大小写不敏感,但是如果涉及到与HTML文档一起工作的时候,class和id名称对大小写是敏感的 一.color color:#ff0000; color:#f00; //缩写 color: ...

  5. Code First开发系列实战之使用EF搭建小型博客平台

    返回<8天掌握EF的Code First开发>总目录 本篇目录 理解应用需求 数据库设计 创建实体数据模型 创建实体类 创建关系和导航属性 实现DbContext类 执行数据访问 理解仓储 ...

  6. ASP.Net请求处理机制初步探索之旅 - Part 5 ASP.Net MVC请求处理流程

    好听的歌 我一直觉得看一篇文章再听一首好听的歌,真是种享受.于是,我在这里嵌入一首好听的歌,当然你觉得不想听的话可以点击停止,歌曲 from 王菲 <梦中人>: --> 开篇:上一篇 ...

  7. NoSQL初探之人人都爱Redis:(1)Redis简介与简单安装

    一.NoSQL的风生水起 1.1 后Web2.0时代的发展要求 随着互联网Web2.0网站的兴起,传统的关系数据库在应付Web2.0网站,特别是超大规模和高并发的SNS类型的Web2.0纯动态网站已经 ...

  8. C#中自己动手创建一个Web Server(非Socket实现)

    目录 介绍 Web Server在Web架构系统中的作用 Web Server与Web网站程序的交互 HTTPListener与Socket两种方式的差异 附带Demo源码概述 Demo效果截图 总结 ...

  9. 用chrome来映射查找样式对应的sass

    较新版本的sass(3.3+)支持source-map功能,可以配合谷歌浏览器或者livestyle来映射查找对应的样式. 要生成source-map可以在grunt中使用 grunt-contrib ...

  10. 为jQuery添加Webkit的触摸方法支持

    前些日子收到邮件,之前兼职的一个项目被转给了其他人,跟进的人来问我相关代码的版权问题. 我就呵呵了. 这段代码是我在做13年一份兼职的时候无聊加上去的,为jQuery添加触摸事件的支持.因为做得有点无 ...