- redis安装及php-redis扩展安装
- 初步使用
- 封装基类 – 单例模式
- 优化封装 – 依赖注入
- 从配置加载
- 从自定义配置加载
本文将一步一步的从redis的安装一直到easySwoole使用高度封装的底层类库,并进行优化提高代码的维护性,可以直接看最后的优化结果
第一部分 redis安装及php-redis扩展安装
redis的安装很简单,直接到redis官网下载,这里使用的是redis4.0.12,下载后直接make && make install即可,
进入到redis的文件夹的src目录,运行一个redis服务,其默认端口是6379:
1 |
./redis-server |
运行一个redis客户端
1 |
./redis-cli |
安装php-redis也很简单,从github把扩展下载下来解压,然后
1 2 3 |
phpize ./configure make && make install |
即可,如果想要configure到指定的php版本就指定phpize的目录并在config的时候prefix到指定的php配置文件,安好之后再php.ini加上redis.so即可。
第二部分 初步使用
直接在源码中进行redis的连接:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<?php /** * Created by bingxiong. * Date: 12/19/18 * Time: 6:38 PM * Description: */ namespace App\HttpController\Api; use \EasySwoole\Core\Component\Di; // 使用封装的redis基类 use App\Lib\Redis\Redis; class Index extends Base { public function getRedis(){ $redis = new \Redis(); $redis->connect("127.0.0.1",6379, 5); $redis->set("bing",19249); return $this->writeJson(200,'OK',$redis->get("bing")); } } |
显然我们不可能这样使用。
第三部分 创建Redis的基类
基类创建在App->Lib->Redis->redis.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
<?php /** * Created by bingxiong. * Date: 12/21/18 * Time: 12:44 AM * Description: */ namespace App\Lib\Redis; // 使用单例模式 use EasySwoole\Config; use EasySwoole\Core\AbstractInterface\Singleton; class Redis { use Singleton; public $redis = ""; private function __construct() { //判断扩展有没有安装 if(!extension_loaded('redis')){ throw new \Exception("redis.so文件不存在"); } try{ $this->redis = new \Redis(); $result = $this->redis->connect("127.0.0.1",6379,3); } catch (\Exception $e){ throw new \Exception("redis服务异常"); } if($result === false){ throw new \Exception("redis连接失败"); } } /** * 重写get友好的返回key不存在的情况 * @param $key * @return bool|string */ public function get($key){ if(empty($key)){ return ''; } return $this->redis->get($key); } } |
说明:
- 使用了单例模式:用于为一个类生成一个唯一的对象。最常用的地方是数据库连接。 使用单例模式生成一个对象后,该对象可以被其它众多对象所使用。作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类。1、一个类只能有一个实例 2、它必须自行创建这个实例 3、它必须自行向整个系统提供这个实例
有了基类之后,配置和连接的任务就从基类的构造函数加载了,之前的代码就变成了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<?php /** * Created by bingxiong. * Date: 12/19/18 * Time: 6:38 PM * Description: */ namespace App\HttpController\Api; use \EasySwoole\Core\Component\Di; // 使用封装的redis基类 use App\Lib\Redis\Redis; class Index extends Base { public function getRedis(){ $result = Redis::getInstance()->get('bing'); return $this->writeJson(200,'OK',$result); } } |
第四部分 依赖注入
依赖注入:一个对象提供另一个对象的依赖关系,是一种设计模式,好处就是有效的分离了对象和它所需要的外部资源,使得它们松散耦合,有利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。
在easyswool使用依赖注入非常的简单,在easyswoolevent的文件中
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public static function mainServerCreate(ServerManager $server,EventRegister $register): void { Di::getInstance()->set('MYSQL',\MysqliDb::class,Array ( 'host' => '127.0.0.1', 'username' => 'root', 'password' => 'root', 'db'=> 'imooc_video', 'port' => 8889, 'charset' => 'utf8') ); Di::getInstance()->set('REDIS',Redis::getInstance()); } |
上面的是我数据库的配置,下面getInstance中实例化了刚才封装的基类
实例化di再getInstance就可以了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<?php /** * Created by bingxiong. * Date: 12/19/18 * Time: 6:38 PM * Description: */ namespace App\HttpController\Api; use \EasySwoole\Core\Component\Di; // 使用封装的redis基类 use App\Lib\Redis\Redis; class Index extends Base { public function getRedis(){ // 3使用依赖注入 $result = Di::getInstance()->get('REDIS')->get('bing'); return $this->writeJson(200,'OK',$result); } } |
第5部分 从配置加载
在配置文件中添加
1 2 3 4 5 |
'REDIS' => [ 'host' => '127.0.0.1', 'port' => 6379, 'time_out' => 3 ] |
然后基类改写成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
<?php /** * Created by bingxiong. * Date: 12/21/18 * Time: 12:44 AM * Description: */ namespace App\Lib\Redis; // 使用单例模式 use EasySwoole\Config; use EasySwoole\Core\AbstractInterface\Singleton; class Redis { use Singleton; public $redis = ""; private function __construct() { //判断扩展有没有安装 if(!extension_loaded('redis')){ throw new \Exception("redis.so文件不存在"); } try{ //从配置加载REDIS - 提高维护性 $redisConfig = Config::getInstance()->getConf("REDIS"); $this->redis = new \Redis(); $result = $this->redis->connect($redisConfig['host'],$redisConfig['port'],$redisConfig['time_out']); } catch (\Exception $e){ throw new \Exception("redis服务异常"); } if($result === false){ throw new \Exception("redis连接失败"); } } /** * 重写get友好的返回key不存在的情况 * @param $key * @return bool|string */ public function get($key){ if(empty($key)){ return ''; } return $this->redis->get($key); } } |
第6部分 从自定义配置加载
由于可能有很多配置,把配置都放在这个文件的话会显得很臃肿,因此我们将每个配置文件比如redis mysql elasticsearch的配置单独抽离出来单独管理,这样有更好的维护性
所以在根目录创建config->redis.php,在这里直接返回redis的配置
1 2 3 4 5 6 7 8 9 |
<?php /** * Created by bingxiong. * Date: 12/21/18 * Time: 2:10 AM * Description: redis相关配置 */ return ['host' => '127.0.0.1', 'port' => 6379, 'time_out' => 3]; |
然后自定义载入配置文件,创建了一个loadConf方法,这个方法在easyswoole的文档中有,所以最终的
EasySwooleEvent.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
<?php /** * Created by PhpStorm. * User: yf * Date: 2018/1/9 * Time: 下午1:04 */ namespace EasySwoole; use App\Lib\Redis\Redis; use \EasySwoole\Core\AbstractInterface\EventInterface; use EasySwoole\Core\Component\Di; use \EasySwoole\Core\Swoole\ServerManager; use \EasySwoole\Core\Swoole\EventRegister; use \EasySwoole\Core\Http\Request; use \EasySwoole\Core\Http\Response; use \EasySwoole\Core\Utility\File; Class EasySwooleEvent implements EventInterface { public static function frameInitialize(): void { // TODO: Implement frameInitialize() method. date_default_timezone_set('Asia/Shanghai'); self::loadConf(EASYSWOOLE_ROOT.'/Config'); } public static function loadConf($ConfPath) { $Conf = Config::getInstance(); $files = File::scanDir($ConfPath); foreach ($files as $file) { $data = require_once $file; $Conf->setConf(strtolower(basename($file, '.php')), (array)$data); } } /** * 使用依赖注入加载 * @param ServerManager $server * @param EventRegister $register */ public static function mainServerCreate(ServerManager $server,EventRegister $register): void { Di::getInstance()->set('MYSQL',\MysqliDb::class,Array ( 'host' => '127.0.0.1', 'username' => 'root', 'password' => 'root', 'db'=> 'imooc_video', 'port' => 8889, 'charset' => 'utf8') ); Di::getInstance()->set('REDIS',Redis::getInstance()); } public static function onRequest(Request $request,Response $response): void { // TODO: Implement onRequest() method. } public static function afterAction(Request $request,Response $response): void { // TODO: Implement afterAction() method. } } |
redis.php 这是redis的基类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
<?php /** * Created by bingxiong. * Date: 12/21/18 * Time: 12:44 AM * Description: */ namespace App\Lib\Redis; // 使用单例模式 use EasySwoole\Config; use EasySwoole\Core\AbstractInterface\Singleton; class Redis { use Singleton; public $redis = ""; private function __construct() { //判断扩展有没有安装 if(!extension_loaded('redis')){ throw new \Exception("redis.so文件不存在"); } try{ // 从自己的配置加载 $redisConfig = Config::getInstance()->getConf("redis"); $this->redis = new \Redis(); $result = $this->redis->connect($redisConfig['host'],$redisConfig['port'],$redisConfig['time_out']); } catch (\Exception $e){ throw new \Exception("redis服务异常"); } if($result === false){ throw new \Exception("redis连接失败"); } } /** * 重写get友好的返回key不存在的情况 * @param $key * @return bool|string */ public function get($key){ if(empty($key)){ return ''; } return $this->redis->get($key); } } |
最终实现的demo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
/** * Created by bingxiong. * Date: 12/19/18 * Time: 6:38 PM * Description: */ namespace App\HttpController\Api; use \EasySwoole\Core\Component\Di; class Index extends Base { public function getRedis(){ // 使用依赖注入 $result = Di::getInstance()->get('REDIS')->get('bing'); return $this->writeJson(200,'OK',$result); } } |