zoukankan      html  css  js  c++  java
  • 构建自己的PHP框架--构建缓存组件(2)

    上一篇博客中使用文件实现了缓存组件,这一篇我们就使用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 attributes
            foreach ($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 sfase;
    
    /**
     * 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' => 'sfcacheRedisCache',
        'redis' => [
            'host' => 'localhost',
            'port' => 6379,
            'database' => 0,
            // 'password' =>'jun',
            // 'options' => [Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP],
        ]
    ];
    

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

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

    <?php
    namespace sfcache;
    
    use Redis;
    use Exception;
    use sfaseComponent;
    
    /**
     * 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

  • 相关阅读:
    理解mipi协议【转】
    Using KernelShark to analyze the real-time scheduler【转】
    内核栈溢出【转】
    检测内核的堆栈溢出【转】
    gcc 编译 + 选项【转】
    service mysqld start 报错:service mysqld start 报错 090517 13:34:15 [ERROR] Can't open the mysql.plugin table. Please run mysql_upgrade to create it. 090Can't open the mysql.plugin table. Please run mysql
    【推荐】MySQL Cluster报错及解决方法(不断更新中)
    MySQL Cluster 配置文件(config.ini)详解
    关于MySQL Cluster集群NoOfReplicas参数问题
    通过PHP current()函数获取未知字符键名数组第一个元素的值
  • 原文地址:https://www.cnblogs.com/CraryPrimitiveMan/p/5449215.html
Copyright © 2011-2022 走看看