【完结】利用 Composer 完善自己的 PHP 框架(三)——Redis 缓存

2014-10-19   /   字数:3005   /   阅读数:45506   /   分类: PHP     

本教程示例代码见 https://github.com/johnlui/My-First-Framework-based-on-Composer


回顾

上两篇文章中我们完成了 View 视图加载类和 Mail 邮件发送类的设计,完成了两个可插拔组件。本篇文章中我们将构建另一个可插拔组件——'Redis 接口',并使用它构建 'MFFC' 的高速缓存服务。

正文

Redis 简介

'Redis' 是一个高性能的 'key-value' 数据库,其 'value' 支持 'String'、'Map(Hash)'、'list'、'set' 和 'sorted sets',中文翻译为 字符串、字典(哈希,在'世界上最好的语言PHP' 中属于 '数组' 的一部分)、列表、集合和有序集合。

我们可以用 Redis 作为高速缓存,存放系统经常需要访问的数据。相比使用文件作为缓存,Redis 拥有更高的性能、更好地可维护性和更强大的操作 API。

Redis 安装

Redis 官网为 http://redis.io/ ,可以很容易地下载安装并在命令行直接启动,它默认监听 '6379' 端口。

Redis 服务端装好并启动之后,并不能写一行代码直接开始使用了,我们还需要安装 '客户端'。目前有两种方式比较推荐:

1. 安装 PHP 的 Redis 扩展

2. 使用 nrk/predis 包。

注意:作为 PHP 扩展安装时,请先打印出 'phpinfo()',找到 'Loaded Configuration File' 这一项,编辑这个 'php.ini' 才有效。别忘了 '重启' Apache 或者 php-fpm。

Redis 使用

我们在此选择 'nrk/predis' 包作为 Redis 驱动。编辑 'composer.json':

"require": {

  "codingbean/macaw": "dev-master",

  "illuminate/database": "*",

  "filp/whoops": "*",

  "nette/mail": "*",

  "predis/predis": "*"

},

运行 'composer update',等待安装完成。

然后我们就要开始构建 Redis 类了,新建 'services/Redis.php':

<?php

use Predis\Client;

/**

* \Redis

*/

class Redis

{

  const CONFIG_FILE = '/config/redis.php';

  protected static $redis;

  public static function init()

  {

    self::$redis = new Client(require BASE_PATH.self::CONFIG_FILE);

  }

  public static function set($key,$value,$time=null,$unit=null)

  {

    self::init();

    if ($time) {

      switch ($unit) {

        case 'h':

          $time *= 3600;

          break;

        case 'm':

          $time *= 60;

          break;

        case 's':

        case 'ms':

          break;

        default:

          throw new InvalidArgumentException('单位只能是 h m s ms');

          break;

      }

      if ($unit=='ms') {

        self::_psetex($key,$value,$time);

      } else {

        self::_setex($key,$value,$time);

      }

    } else {

      self::$redis->set($key,$value);

    }

  }

  public static function get($key)

  {

    self::init();

    return self::$redis->get($key);

  }

  public static function delete($key)

  {

    self::init();

    return self::$redis->del($key);

  }

  private static function _setex($key,$value,$time)

  {

    self::$redis->setex($key,$time,$value);

  }

  private static function _psetex($key,$value,$time)

  {

    self::$redis->psetex($key,$time,$value);

  }

}

新建配置文件 'config/redis.php':

<?php

return [

  'host' => '127.0.0.1',

  'port' => 6379

];

然后我们就可以开始测试啦~ 在 'HomeController' 中增加:

Redis::set('key','value',5,'s');

echo Redis::get('key');

运行一次后将上面一行注释掉,不断刷新,看 'value' 是否会在设定的时间结束后从页面上消失。

代码分析

1. 我们创建了 '\Redis' 类,提供了 '::set()'、'::get()' 和 '::delete()' 三个静态方法,用于新增、获取和删除一对 'key-value'。

2. '::set()' 方法支持设定 'key-value' 键值对的生命周期,并支持 'h'、'm'、's' 和 'ms' 四个单位,代表时、分、秒和毫秒,这样就可以方便地用于缓存了。

3. 严格意义上讲,缓存类至少还需要一个 '判断 key 是否还存在' 的基本操作,所以这个类还只是一个略微强大的 Redis 接口。

4. 建造缓存接口作为练习,大家可以尝试自己动手写一下。选择新建 Cache 类或者在 Redis 类中新增接口均可。


【完结】

WRITTEN BY

avatar

评论:

suhern
2018-10-18 15:25
感謝!
另外 init() 內好像應該要 singleton 模式來避免建立多個 client 物件多條連線?
小龙
2018-05-17 22:44
老大问一下,如何CLI 方式来运行呢..???
小龙
2018-05-13 22:30
老大请问一下,vend/resque 这个轮子怎么用,用不起来,

-----------------------------
$resque = new Resque($client);
    $id = $resque->enqueue('default_queue', 'app\controllers\job\Job', array('foo' => 'bar'), true);    
    echo '<Br>';
    
    
    $factory = new \Resque\Job\StatusFactory($resque);

    // Pass the ID returned from enqueue
    $status = $factory->forId($id);
    
    // Alternatively, to get the status for a Job instance:
    //$status = $factory->forJob($job);
    
    // Outputs the status as a string: 'waiting', 'running', 'complete', etc.
    echo $status->getStatus();
    
    echo '<Br>';
    
    echo $id;exit;
---------------------
waiting
7f491564609f8ab7aa95da6ee41bfeee

-----------------
cli 模式不行呢?没有一个成功的。

/usr/local/servers/php/bin/php /usr/local/servers/nginx/html/led/my_kj resque queue:list

/usr/local/servers/php/bin/php /usr/local/servers/nginx/html/led/my_kj resque worker -Q default -Q default_queue

/usr/local/servers/php/bin/php /usr/local/servers/nginx/html/led/my_kj vendor/vend/resque queue:list

/usr/local/servers/php/bin/php /usr/local/servers/nginx/html/led/my_kj/vendor/vend/resque worker -Q default -Q default_queue

/usr/local/servers/php/bin/php /usr/local/servers/nginx/html/led/my_kj/vendor/vend/resque enqueue default_queue 'app\controllers\job\Job' -t
/usr/local/servers/php/bin/php /usr/local/servers/nginx/html/led/my_kj/vendor/vend/resque queue:list
小龙
2018-05-13 11:34
老大可以说一下,怎么装chrisboulton/php-resque-scheduler  的轮子吗,谢谢了。

https://packagist.org/packages/chrisboulton/php-resque-scheduler

按照上面的实例,感觉格格不入

Warning: require(Resque/Resque.php): failed to open stream: No such file or directory in Index.php on line 57

Fatal error: require(): Failed opening required 'Resque/Resque.php' (include_path='.;C:\php\pear') in Index.php on line 57
樱桃小盒子
2018-04-23 11:49
laravel入门就是跟着博主的教程一步步走的,超级感谢博主
这套composer教程也很棒,用了蛮久laravel,事实上对基础的东西还是很生,
能不能请博主多讲讲redis相关?或推荐下redis相关的资料或书籍?
0318_xy
2018-02-12 17:20
我的天啊
终于找到原因了
Error thrown with message "Non-static method Redis::set() cannot be called statically"
这个是因为安装了 PHP 的 Redis 扩展   跟  用  nrk/predis  引入这种方法  新建的 redis.php 重名导致的
解决方案 是
把service下的  redis.php  换个名字  然后重新  composer dump-autoload

另外因为我复制的时候  漏复制了redis.php的第一句  use Predis\Client;
所以一直报错
Error thrown with message "Class 'Client' not found"

完了 被自己蠢苦
博主写的真的很好,对我这种想学习又不知道从何下手的 小白来说 真的帮助很大
学到这里 开始对composer有点了解了 ,还会再重新看两遍,我第一遍一般是为了实现,因为我手残 经常跟着做都做不好
嗯 很感谢博主的分析
0318_xy
2018-02-12 16:35
Error thrown with message "Non-static method Redis::set() cannot be called statically"

Redis::set('key','value',5,'s');  报错了  哪位大神知道怎么解决,卡着了
tanxinchao
2018-01-28 21:14
Redis类未找到,需要composer dump-autoload
钻迹
2017-12-02 11:08
不错不错,最近想用 laravel 构建一个个人网站,跟着你的教程,对框架的设计又多了些理解。
暮隼
2017-10-12 20:09
和你一样热爱着php和swift,但每次都是向你学习。
Lichmaker
2017-08-30 16:57
搞懂了,翻看redis文档得知,原来是redis的指令,SETEX是以秒为单位,PSETEX是以毫秒为单位,再次感谢!
Lichmaker
2017-08-30 16:53
你好~看完整个教程真的受益匪浅,前面都很浅显易懂,但是这里我看源代码看了一下午,还是没有搞懂static function _setex() 和static function _psetex()的作用是什么。希望能得到一些指导,谢谢!
路过
2017-07-23 21:17
跟着做,明白了 composer 原来是这么用的,感觉自己还是太早使用laravel了,反倒是这个小框架让我学到了不少东西
zmecust
2017-07-14 10:23
要是加入中间件 Middleware 就好了
markstary
2017-07-07 16:19
留下我的小脚印,真的受益匪浅,跟着敲了一部分
chen
2017-07-06 14:26
我发现我跟着教程弄出来框架后竟然不会用
码农小学生
2017-07-03 16:53
这个教程写的一般般。这样自的框架用处不大,太鸡肋了
JohnLui
2017-07-03 17:28
@码农小学生:等你看到一个东西不再想“这哥们儿是不是比我弱”的时候,你就真的变强了。
对对对
2016-12-25 14:05
大神.我集成的smarty模板表单的url怎么写啊
Tony
2016-12-21 14:18
终于搞明白Composer怎么用了,感谢博主!
ricebna
2016-11-28 23:06
请问阁下 lumen相比阁下的tinylara框架,怎么比较呢。
loodeer
2016-09-21 22:07
非常赞!!1
伊布
2016-09-08 20:39
确实受益良多,循序渐进的教学让人记忆深刻
螃蟹壳
2016-07-13 10:23
好东西,正是我想要的!
攻城獭
2016-07-08 10:59
一直想自己写一个框架,照着大神的教程敲了一遍,框架很小很轻盈,受益良多。谢谢。
南山小娇
2016-03-23 15:28
受益良多!
Jason
2015-12-04 17:03
学习了!  很棒! 更好的了解了 composer, 大赞!

也会继续关注了楼主在Github 上的TinyLara 项目.

建议:
Redis::init() 方法是否可以使用单例模式,每个命令都new一个比较浪费吧...
linice
2015-11-06 15:58
一段时间不关注你的博客,发现都已经把此MFFC发布成为了TinyLara框架。
现在看这里,是因为自己渐渐发现各种框架总有一些不如意的地方,于是,想自己composer一个,就把大神你的内容演练一遍。
真心感谢!!!
xiaowie
2015-10-04 16:36
我也自己搞了个框架,不过数据库那块用了我自己写的类,增加了文件上传啥的,功能也齐全了。不过我想问下,你有没有试过你的tinylara框架的分页?
小宇宙
2015-08-29 16:42
照着教程写了一遍,感觉composer 真的好强大。 谢谢您的热心分享。
MIchale
2015-08-17 21:55
大赞,照着做了一遍。要是能在框架当中,使用更多的设计模式就好了。我发现了一个问题,Redis::init()每次调用的时候都会实例化Client
tangtang
2015-08-04 19:49
老大 Cannot redeclare class Redis  这个是什么错?
JohnLui
2015-08-04 20:31
@tangtang:把你的那个 PHP 的扩展 Redis 驱动删掉就行。
Kent
2015-07-24 16:28
大神,为什么我会调用redis的set方法的时候会报错。
Non-static method Redis::set() cannot be called statically, assuming $this from incompatible context
JohnLui
2015-07-24 17:08
@Kent:因为你把 public static function set 写成了 public function set
Kent
2015-07-24 17:16
@JohnLui:没有啊,就是static,而且我刚下载了你的源码,部署到我的环境下,还是一样,我的是php5.6,会不会和这个有关?
JohnLui
2015-07-24 17:18
@Kent:不科学 可能你在其他地方写了一个 Redis 类,一直改的不是那个类的代码?
Kent
2015-07-24 17:19
@JohnLui:并没有写啊。。一直按着你的教程来的。。你的这个demo还在吗?是不是也有这个问题?
上山若水
2015-10-01 22:58
@JohnLui:这是因为在他的系统里面已经装过Redis PHP扩展了
JohnLui
2015-07-24 17:35
@Kent:你直接试着跑一下这个,看看 https://github.com/johnlui/My-First-Framework-based-on-Composer
Kent
2015-07-24 17:39
@JohnLui:跑了,不行啊,刚才就下了,不过我找到原因了,services/Redis.php的类名和php自带的redis类重名了,所以。。你懂的,改下类名就可以了
jim
2016-08-30 14:37
@JohnLui:碰到同样的问题,但解决方式不一样。

// use Redis;  //引入这个就会报错
use Illuminate\Support\Facades\Redis as Redis;  //引入这个就ok


http://xwsoul.com/posts/1025
JohnLui
2015-07-27 01:14
@Kent:PHP 没有自带 Redis 类,是你装了那个 PHP 插件形式的 Redis 驱动吧?
Kent
2015-07-27 08:53
@JohnLui:就是为了让php支持redis,装了个扩展
Lzty
2016-05-10 09:28
@Kent:怎么解决的?
sds
2015-07-23 20:38
很强大的框架,,学习了。。
860262755
2015-03-05 21:15
非常棒~~~~~~~~~期待跟新
lurenjia
2015-02-15 14:37
受益匪浅,,感谢啊
zhkzyth
2015-01-02 17:24
好棒~~谢谢JohnLui的文章,让我对composer、组件化框架、什么是框架有了更多的认识。
leeir
2014-12-31 15:53
楼主   你的文章读完受益匪浅   不知能否和你交个朋友   留个QQ或者其他即时聊天工具   谢谢!
JohnLui
2015-01-04 10:54
@leeir:邮箱就可以了啦~
dororo
2014-11-07 18:00
非常棒!!

2014-11-03 14:39
写的真不错,赞一个!
yuanchao
2014-10-30 16:20
请问下,这系列的文章还会更新吗?
JohnLui
2014-10-30 16:26
@yuanchao:不会了,我以后就主要完善 TinyLara 框架了。
yuanchao
2014-10-30 16:28
@JohnLui: 恩恩,期待你的tinyLara 框架大放异彩!
JohnLui
2014-10-30 16:33
@yuanchao:谢谢~
dsfds
2015-07-23 11:14
@yuanchao:不错!
dsfds
2015-07-23 11:14
@JohnLui:不错!!!!!!!!!
yuanchao
2014-10-29 22:49
终于把您的这系列的文章看完了,受益匪浅,谢谢
JohnLui
2014-10-29 23:04
@yuanchao:能对你有帮助我也非常开心!

发表评论:

© 2011-2024 岁寒  |  Powered by Emlog