上一篇博客中使用文件实现了缓存组件,这一篇我们就使用Redis来实现一下,剩下的如何使用memcache、mysql等去实现缓存我就不一一去做了。

首先我们需要安装一下 redis 和 phpredis 库,phpredis 项目在github上的地址:https://github.com/phpredis/phpredis 。相应的文档也在上面。

先在 src/cache 文件夹下创建 RedisCache.php 文件。在写组件的时候发现我们缺少一个地方去创建一个 Redis 的实例,并且是在创建 cahce 实例之后,返回给Yii::createObject 方法之前。所以我们修改了 src/Sf.php 文件,其 createObject 方法的内容如下:

  1. public static function createObject($name)
  2. {
  3. $config = require(SF_PATH . "/config/$name.php");
  4. // create instance
  5. $instance = new $config['class']();
  6. unset($config['class']);
  7. // add attributes
  8. foreach ($config as $key => $value) {
  9. $instance->$key = $value;
  10. }
  11. $instance->init();
  12. return $instance;
  13. }

对比之前的代码,不难发现其实只添加了一行 $instance->init(); ,这样我们就可以在 init 方法中去创建相应的 Redis 实例,并保存下来。但这样又会引入一个问题,所有使用 Yii::createObject 创建的实例都必须含有 init 方法(当然你也可以判断有没有这个方法)。那我们就来实现一个基础类 Component ,并规定所有使用 Yii::createObject 创建的实例都集成它,然后再在 Component 中加入 init 方法即可。

为什么选择这种做法,而不是使用判断 init 方法存不存在的方式去解决这个问题,主要是考虑到之后可能还需要对这些类做一些公共的事情,就提前抽出了 Component 类。

Component 类现在很简单,其内容如下:

  1. <?php
  2. namespace sf\base;
  3. /**
  4. * Component is the base class for most sf classes.
  5. * @author Harry Sun <sunguangjun@126.com>
  6. */
  7. class Component
  8. {
  9. /**
  10. * Initializes the component.
  11. * This method is invoked at the end of the constructor after the object is initialized with the
  12. * given configuration.
  13. */
  14. public function init()
  15. {
  16. }
  17. }

之后再定义一下 Redis 缓存的配置如下:

  1. <?php
  2. return [
  3. 'class' => 'sf\cache\RedisCache',
  4. 'redis' => [
  5. 'host' => 'localhost',
  6. 'port' => 6379,
  7. 'database' => 0,
  8. // 'password' =>'jun',
  9. // 'options' => [Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP],
  10. ]
  11. ];

其中 password 和 options 是选填,其它是必填。

剩下的就是相关实现,就不一一细说了,代码如下:

  1. <?php
  2. namespace sf\cache;
  3. use Redis;
  4. use Exception;
  5. use sf\base\Component;
  6. /**
  7. * CacheInterface
  8. * @author Harry Sun <sunguangjun@126.com>
  9. */
  10. class RedisCache extends Component implements CacheInterface
  11. {
  12. /**
  13. * @var Redis|array the Redis object or the config of redis
  14. */
  15. public $redis;
  16. public function init()
  17. {
  18. if (is_array($this->redis)) {
  19. extract($this->redis);
  20. $redis = new Redis();
  21. $redis->connect($host, $port);
  22. if (!empty($password)) {
  23. $redis->auth($password);
  24. }
  25. $redis->select($database);
  26. if (!empty($options)) {
  27. call_user_func_array([$redis, 'setOption'], $options);
  28. }
  29. $this->redis = $redis;
  30. }
  31. if (!$this->redis instanceof Redis) {
  32. throw new Exception('Cache::redis must be either a Redis connection instance.');
  33. }
  34. }
  35. /**
  36. * Builds a normalized cache key from a given key.
  37. */
  38. public function buildKey($key)
  39. {
  40. if (!is_string($key)) {
  41. $key = json_encode($key);
  42. }
  43. return md5($key);
  44. }
  45. /**
  46. * Retrieves a value from cache with a specified key.
  47. */
  48. public function get($key)
  49. {
  50. $key = $this->buildKey($key);
  51. return $this->redis->get($key);
  52. }
  53. /**
  54. * Checks whether a specified key exists in the cache.
  55. */
  56. public function exists($key)
  57. {
  58. $key = $this->buildKey($key);
  59. return $this->redis->exists($key);
  60. }
  61. /**
  62. * Retrieves multiple values from cache with the specified keys.
  63. */
  64. public function mget($keys)
  65. {
  66. for ($index = 0; $index < count($keys); $index++) {
  67. $keys[$index] = $this->buildKey($keys[$index]);
  68. }
  69. return $this->redis->mGet($keys);
  70. }
  71. /**
  72. * Stores a value identified by a key into cache.
  73. */
  74. public function set($key, $value, $duration = 0)
  75. {
  76. $key = $this->buildKey($key);
  77. if ($duration !== 0) {
  78. $expire = (int) $duration * 1000;
  79. return $this->redis->set($key, $value, $expire);
  80. } else {
  81. return $this->redis->set($key, $value);
  82. }
  83. }
  84. /**
  85. * Stores multiple items in cache. Each item contains a value identified by a key.
  86. */
  87. public function mset($items, $duration = 0)
  88. {
  89. $failedKeys = [];
  90. foreach ($items as $key => $value) {
  91. if ($this->set($key, $value, $duration) === false) {
  92. $failedKeys[] = $key;
  93. }
  94. }
  95. return $failedKeys;
  96. }
  97. /**
  98. * Stores a value identified by a key into cache if the cache does not contain this key.
  99. */
  100. public function add($key, $value, $duration = 0)
  101. {
  102. if (!$this->exists($key)) {
  103. return $this->set($key, $value, $duration);
  104. } else {
  105. return false;
  106. }
  107. }
  108. /**
  109. * Stores multiple items in cache. Each item contains a value identified by a key.
  110. */
  111. public function madd($items, $duration = 0)
  112. {
  113. $failedKeys = [];
  114. foreach ($items as $key => $value) {
  115. if ($this->add($key, $value, $duration) === false) {
  116. $failedKeys[] = $key;
  117. }
  118. }
  119. return $failedKeys;
  120. }
  121. /**
  122. * Deletes a value with the specified key from cache
  123. */
  124. public function delete($key)
  125. {
  126. $key = $this->buildKey($key);
  127. return $this->redis->delete($key);
  128. }
  129. /**
  130. * Deletes all values from cache.
  131. */
  132. public function flush()
  133. {
  134. return $this->redis->flushDb();
  135. }
  136. }

访问 http://localhost/simple-framework/public/index.php?r=site/cache 路径,得到结果如下:

  1. 我就是测试一下缓存组件

这样我们完成了使用 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. FTD团队目录

    一.Daily Scrum Meeting[Alpha] · [Alpha]Daily Scrum Meeting 第一次 · [Alpha]Daily Scrum Meeting 第二次 · [Al ...

  2. QComboBox的activated与currentIndexChanged的区别

    void activated ( int index ) void activated ( const QString & text ) 信号activated是只要单击选择框即使所选内容选择 ...

  3. Java_正则表达式

    1.简介 正则表达式是一串特定字符串,组成一个“规则字符串”,这个“规则字符串”是描述文本规则的工具.正则表达式就是记录文本规则的代码. 2.字符集合 [abc] a,b,c中任意一个字符 [^abc ...

  4. ASP.NET中基本语言特性

    自动属性 public string Name { get; set; } 对象与集合的初始化 //自动推断类型//集合的初始化 var Products=new List<Product> ...

  5. 数据分析之Numpy基础:数组和适量计算

    Numpy(Numerical Python)是高性能科学计算和数据分析的基础包. 1.Numpy的ndarray:一种多维数组对象 对于每个数组而言,都有shape和dtype这两个属性来获取数组的 ...

  6. Hbuilder开发HTML5 APP之创建子页面

    折腾了好久,终于看明白怎么创建了: 1.创建个html5的mui页面,在其初始化方法中: mui.init({   subpages:[{    id:"list",   url: ...

  7. Javascript分号,加还是不加?

    关于这个问题,网上已经有很多人讨论过了,我先说说自己对这个问题的回答:加!(但非必须) 有些人写代码,懒得加分号,除非是迫不得已才勉强放一个分号上去.如果你可以保证你写的代码不出现任何 bug,那当然 ...

  8. Copy 与MutableCopy的区别

    NSString *string = @"origion"; NSString *stringCopy = [string copy]; NSMutableString *stri ...

  9. 先有 Mac 还是先有银元?

    自从开设了这个公众号以后,收到最多的问题是:听了 Mac 君的介绍,我也觉得 Mac 很好,可是穷屌丝一枚,真买不起,怎么破?前几天我在微博上说,读了我的书,就有 Mac 了.居然有读者来问:这是真的 ...

  10. WCF 的 Service Instance模式和并发处理

    WCF 的 Service Instance(实例)有三种模式 PerCall:每一次调用都创建一个实例,每一次调用结束后回收实例.此模式完全无状态. PerSession:调用者打开Channel时 ...