上一篇博客中使用文件实现了缓存组件,这一篇我们就使用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 attributesforeach ($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

转载于:https://www.cnblogs.com/CraryPrimitiveMan/p/5449215.html

构建自己的PHP框架--构建缓存组件(2)相关推荐

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

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

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

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

  3. 构建你的第一个Vue.js组件

    我记得当时我拿起CakePHP,我很喜欢,开始使用它是多么容易.这些文档不仅结构合理,详尽无遗,而且用户友好.多年以后,这正是我在Vue.js中感受到的.然而,与Cake相比,Vue文档仍然缺少一件事 ...

  4. 录制完脚本怎么做接口自动化测试_快速构建轻量级接口自动化框架

    随着移动互联网和微服务的迅速发展,大部分企业都采用接口的方式实现客户端和服务端的交互,传统的PC端也逐渐趋向于前后端分离架构.为了应对此种架构下的业务迭代,很多QA团队开始推广接口自动化,甚至是自研接 ...

  5. 基于ForkJoin构建一个简单易用的并发组件

    2019独角兽企业重金招聘Python工程师标准>>> 基于ForkJoin构建一个简单易用的并发组件 在实际的业务开发中,需要用到并发编程的知识,实际使用线程池来异步执行任务的场景 ...

  6. mezzanine-一个功能强大且易于扩展性的Django框架构建的内容管理平台

    mezzanine是一个功能强大且灵活的内容管理平台. Mezzanine使用Django框架构建,提供了一个简单但高度可扩展的体系结构,我们鼓励您深入研究和修改代码.Mezzanine是BSD许可的 ...

  7. Vue.js构建用户界面的渐进式框架(前端学习笔记1.0)

    文章目录 前言 一.Vue是什么? 二.前端核心分析 1.1.概述 1.2.前端三要素 1.3.结构层(HTML) 1.4.表现层(CSS) 1.5.行为层(JavaScript) 二.前端发展史 2 ...

  8. 基于Spring4+SpringMVC4+Mybatis3+Hibernate4+Junit4框架构建高性能企业级的部标1077视频监控平台...

    开发企业级的部标GPS监控平台,投入的开发力量很大,开发周期也很长,选择主流的开发语言以及成熟的开源技术框架来构建基础平台,是最恰当不过的事情,在设计之初就避免掉了技术选型的风险,避免以后在开发过程中 ...

  9. 构建Java并发模型框架

    2002 年 2 月 22 日 Java的多线程特性为构建高性能的应用提供了极大的方便,但是也带来了不少的麻烦.线程间同步.数据一致性等烦琐的问题需要细心的考虑,一不小心就会出现一些微妙的,难以调试的 ...

最新文章

  1. java类加载是什么意思_java 类加载机制有什么用
  2. 【 Verilog HDL 】HDL的三种描述方式
  3. 名校华人教授专门设局诈骗中国留学生,4年吸金超百万美元,连亲戚也没放过...
  4. flatmap 与map 的区别 java_map和flatmap的区别+理解、学习与使用 Java 中的 Optional
  5. python hmac
  6. 详细分析TCP数据的传输过程
  7. IPC--进程间通信五(信号)
  8. python3 ftp服务器_python3实现ftp服务功能(服务端 For Linux)
  9. 2021年最新的Java面试题,精选100题,大厂必备
  10. python中str类型_python的str是什么类型
  11. innodb_file_per_table参数
  12. 445.两数相加II
  13. linux高级技巧:rsync同步(二)
  14. 怎样关闭计算机445端口,445端口怎么关闭 445端口关闭方法介绍
  15. android mac地址 伪装,教你伪装MAC地址
  16. 大型文件传输,前后端分别怎么处理?
  17. 简单的摄像头自写驱动程序总结
  18. Error: Incorrect contents fetched, please reload.
  19. AVB之镜像的签名及验证签名详解
  20. 马云关于计算机名言,49句关于马云的名言

热门文章

  1. 漫步数学分析四——集合内部
  2. 一个寄存器有几个字节_STM32f103ZET6 学习资料 (连载2 寄存器的操作界限)
  3. UML表示实体类型和属性
  4. 改善深层神经网络:超参数调整、正则化以及优化——2.8 Adam算法(Adaptive Moment Estimation)
  5. 【局部敏感度的问题代码实现】差分隐私代码实现系列(八)
  6. IPC--进程间通信一(管道)
  7. html织梦站内搜索代码,简单三步-实现dede站内搜索功能
  8. mysql limit 表的长度_mysql中的limit用法有哪些(推荐)
  9. python 邮件发送附件 本目录下所有文件_为python中的每个txt文件发送附件电子邮件...
  10. pwm调速流程图小车_PWM调速+循迹__智能小车程序