【完结】利用 Composer 完善自己的 PHP 框架(三)——Redis 缓存
本教程示例代码见 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 类中新增接口均可。
【完结】
评论:
2018-05-13 22:30
-----------------------------
$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
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
这套composer教程也很棒,用了蛮久laravel,事实上对基础的东西还是很生,
能不能请博主多讲讲redis相关?或推荐下redis相关的资料或书籍?
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有点了解了 ,还会再重新看两遍,我第一遍一般是为了实现,因为我手残 经常跟着做都做不好
嗯 很感谢博主的分析
2018-02-12 16:35
Redis::set('key','value',5,'s'); 报错了 哪位大神知道怎么解决,卡着了
2015-12-04 17:03
也会继续关注了楼主在Github 上的TinyLara 项目.
建议:
Redis::init() 方法是否可以使用单例模式,每个命令都new一个比较浪费吧...
2015-11-06 15:58
现在看这里,是因为自己渐渐发现各种框架总有一些不如意的地方,于是,想自己composer一个,就把大神你的内容演练一遍。
真心感谢!!!
2015-07-24 16:28
Non-static method Redis::set() cannot be called statically, assuming $this from incompatible context
2015-07-24 17:35
2018-10-18 15:25
另外 init() 內好像應該要 singleton 模式來避免建立多個 client 物件多條連線?