redis封装代码

redis封装代码

为了更好更方便的使用redis,做了一个redis封装的类,

redis key的结构为:global Pre(缺省时,默认使用表前缀) + table name(除前缀的数据表明) + id(数据表主键id).以数据表主键id作为redis的区分,不同的子类(model)定义不同的redis前缀,

取redis时,如果拿不到数据,则会到数据库中查询相应的数据(以传入id为查询依据)

子类实例化时,必须要声明对应的数据表

子类也可以关联其他的子表,比如查商品表,可以通过关联sku表,顺带查询出相应的sku数据

使用本实例,需自行实现通过sql查询功能

1、配置文件

 array(
        'host' => '127.0.0.1',     //redis 主机地址 
        'port' => '6379',              //端口号  6379
        'pwd' => '',   //密码  //
    ),
);

2、redis基类

get 必须传第二个参数
  $this->_table = array(
    'mainTable' => array(
        'table' => 'abroad_goods',
        'fields' => '*',
        'name' => 'ag_id'
    ),
    'subTable' => array(
        //keyName 为子表数据在返回值中的key名称,必须
        array(
            'table' => 'abroad_order',
            'fields' => '*',
            'keyName' => 'x1',
            'name' => 'ao_ag_id',
            'order' => 'ao_id DESC',
            'where' => array(
                array('name' => 'ao_goods_name', 'oper' => 'like', 'value' => ''%说法%''),
                array('name' => 'ao_status', 'oper' => '=', 'value' => '1'),   //只查有用的数据  缓存到内存中
            )
        ),
        array(
            'table' => 'abroad_order',
            'fields' => '*',
            'keyName' => 'x2',
            'name' => 'ao_ag_id',
            'order' => 'ao_id DESC',
            'where' => array(
                array('name' => 'ao_goods_name', 'oper' => 'not like', 'value' => ''%说法%''),
            )
        ),
    )
);*/
class App_Model_Redis_RedisAbroadBaseStorage
{
    private $redis = null;           //redis实例
    protected $_redis_pre = '';     //当前模型redis数据前缀  默认为 _table_pre
    protected $_table_pre = '';     //默认拿config/mysql.php 中的tablepre
    protected $_table;
    /**
     * App_Model_Redis_RedisAbroadBaseStorage constructor.
     * 使用到了系统DB类的两个方法( fetch_first 和 fetch_all),如果要移植到其他项目,请实现此类,或作相应改动
     */
    public function __construct() {
        $redis_config = plum_parse_config('redis_config', 'redis');
        $this->setTablePre();
        $this->redis = new Redis();
        if ($this->redis->connect($redis_config['host'], $redis_config['port']) == false) {
            die($this->redis->getLastError());
        }
        //如果有密码,则调用auth
        if ($redis_config['pwd'] !== '') {
            if ($this->redis->auth($redis_config['pwd']) == false) {
                die($this->redis->getLastError());
            }
        }
    }
    /**
     * @param $tableArr 设置模型数据表信息
     */
    public function setTableData($tableArr) {
        $this->_table = $tableArr;
    }
    /**
     * 获取模型数据表信息
     */
    public function getTableData() {
        return $this->_table;
    }
    /**
     * 设置表前缀,如果子类有传入,则使用传入值,
     * 否则使用系统配置 config/mysql.php
     */
    private function setTablePre() {
        $query = plum_parse_request_uri();
        $prefix = array_shift($query);
        if ($prefix == 'manageadmin') {
            $db_config = plum_parse_config('manageadmin', 'mysql');
        } else {
            $db_config = plum_parse_config('default', 'mysql');
        }
        $this->_table_pre = $this->_table_pre ? $this->_table_pre : $db_config['tablepre'];
    }
    /**
     * @return string redis key前缀
     */
    public function getPre() {
        return $this->_redis_pre ? $this->_redis_pre : $this->_table_pre;
    }
    /**
     * 重新设置前缀
     * @param $pre string 前缀
     */
    public function setPre($pre) {
        $this->_redis_pre = $pre;
    }
    /**
     * redis完整key为: redis前缀 + 主表名 + id
     * @param $id
     * @return string 组装redis key
     */
    public function getKey($id) {
        $table_name = isset($this->_table['mainTable']['table']) ? $this->_table['mainTable']['table'] : 'no_table';
        return $this->getPre() . $table_name . '_' . $id;
    }
    /**
     * 获取redis的值
     * 先查redis  如果没有 去查mysql  如果还没有 则返回null
     * @param $id int id
     * @param $hasDataBase bool  默认没有查到数据时,去数据库拿数据
     * @return string 有数据返回序列化后的数据,没数据返回空字符串
     */
    public function get($id, $hasDataBase = true) {
        $key = $this->getKey($id);
        if ($this->redis->exists($key)) {
            $res = $this->redis->get($key);
        } elseif ($hasDataBase && isset($this->_table['mainTable']['table'])) {
            //没有的话,去数据库查询
            $res = $this->queryData($id);
            $this->set($id, $res);
            $res = $this->redis->get($key);
        } else {
            return '';
        }
        return unserialize($res);
    }
    /**
     * 如果主表数据为空,则不再查询子表,但相反,子表可以为空
     * @param $id int 表id
     * @return mixed array 查询得到的数据
     */
    private function queryData($id) {
        $data = DB::fetch_first($this->formatSql($this->_table['mainTable'], $id));
        if (empty($data)) {
            return array();
        }
//        $data = $this->object2array($data);
        if (!empty($this->_table['subTable'])) {
            foreach ($this->_table['subTable'] as $info) {
                $data[$info['keyName']] = DB::fetch_all($this->formatSql($info, $id));
            }
        }
        return $data;
    }
    /**
     * @param $tableInfo array 表信息
     * @param $id int 主表主键id
     * @return string 返回组织后的sql
     */
    private function formatSql($tableInfo, $id) {
        $fields = $tableInfo['fields'] ? $tableInfo['fields'] : '*';
        $sql = "SELECT " . $fields . " FROM " . $this->_table_pre . $tableInfo['table'] . ' '; //" WHERE " . $tableInfo['name'] . " = '" . $id . "' ";
        $sql .= $this->formatWhere($tableInfo, $id);
        $sql .= $this->formatOrder($tableInfo);
        return $sql;
    }
    /**
     * 拼接sql
     * @param $tableInfo
     * @param $id
     * @return mixed
     */
    private function formatWhere($tableInfo, $id) {
        $whereSql = '';
        if (isset($tableInfo['where'])) {
            $whereSql = ' WHERE 1=1 ';
            if (!empty($tableInfo['where'])) {
                foreach ($tableInfo['where'] as $v) {
                    $value = isset($v['value']) ? $v['value'] : $id;
                    $oper = isset($v['oper']) ? $v['oper'] : '=';
                    switch ($oper) {
                        case 'in':
                        case 'not in':
                            $whereSql .= " AND " . $v["name"] . " " . $oper . " (" . trim($value, ",") . ") ";
                            break;
                        default:
                            $whereSql .= " AND " . $v["name"] . " " . $oper . " " . trim($value, ",") . " ";
                            break;
                    }
                }
            }
        }
        return $whereSql;
    }
    /**
     * @param $tableInfo 数据表
     * @return string 返回值
     */
    private function formatOrder($tableInfo) {
        $orderSql = '';
        if (isset($tableInfo['order'])) {
            $orderSql = ' order by ' . $tableInfo['order'] . ' ';
        }
        return $orderSql;
    }
    /**
     * @param $id
     * @param $value
     * @param int $expire 过期时间  单位:秒 。默认(-1)为不限
     * @param bool $isNewExpire 如果是有过期时间的,是否重新生成,即从更新那一刻起,重新倒计时
     * @return true
     */
    public function set($id, $value, $expire = -1, $isNewExpire = true) {
        $key = $this->getKey($id);
        $value = $value ? serialize($value) : ''; //序列化数据 空字符不序列化
        if ($expire > -1) {
            if ($isNewExpire) {
                $this->redis->set($key, $value);
                $this->expire($id, $expire);
            } else {
                $leftTime = $this->redis->ttl($key);
                $this->redis->set($key, $value);
                $this->expire($id, $leftTime);
            }
        } else {
            $this->redis->set($key, $value);
        }
        return true;
    }
    /**
     * @param $id
     * @return bool|true
     */
    public function update($id) {
        $res = $this->queryData($id);
        return $this->set($id, $res);
    }
    /**
     * @param $idArr array 要查询的数据的key数组
     * @return array 返回查询到的缓存数据,与传入参数数据结构一致
     */
    public function mget($idArr) {
        $return = array();
        foreach ($idArr as $k => $v) {
            $return[$k] = $this->get($v);
        }
        return $return;
    }
    /**
     * 批量存储
     * @param $arr array 要设置的数组,数组的key作为redis的key,value作为redis的value
     * @return bool 有数据的话返回数组
     */
    public function mset($arr) {
        $msetArr = array();
        if (!empty($arr)) {
            foreach ($arr as $k => $v) {
                $key = $this->getKey($k);
                $msetArr[] = array($key => $v);
            }
            return $this->redis->mset($msetArr);
        }
        return false;
    }
    /**
     * @param $id int 数据id
     * @param $second int 过期时间,单位:秒
     * @return true|false
     */
    public function expire($id, $second) {
        $key = $this->getKey($id);
        return $this->redis->expire($key, $second);
    }
    /**
     * @param $ids array 要删除的数据的id,单个可以为字符串,多个需要是id 数组
     * @return int 删除的数量
     */
    public function del($ids) {
        if (is_array($ids)) {
            $keyArr = array();
            foreach ($ids as $val) {
                $keyArr[] = $this->getKey($val);
            }
            return $this->redis->del($keyArr);
        } else {
            $key = $this->getKey($ids);
            return $this->redis->del($key);
        }
    }
    /**
     * 默认不对外开发,如果要使用,请在子类重载
     * @return bool 删除所有 为了数据安全 此接口不对外开放
     */
    protected function flashAll() {
        return $this->redis->flushAll();
    }
    /**
     * 根据正则表达式 获取当前系统的key
     * @param $pattern string 正则表达式
     * @return array keys(*):当前系统所有的key ,
     */
    public function keys($pattern) {
        return $this->redis->keys($pattern);
    }
    /**
     * 对应
     * @param $id int剩余时间 time to left
     * @return int 单位:秒,
     */
    public function ttl($id) {
        $key = $this->getKey($id);
        return $this->redis->ttl($key);
    }
    /**
     * 当前key是否存在
     * @param $id
     * @return bool
     */
    public function exists($id) {
        $key = $this->getKey($id);
        return $this->redis->exists($key);
    }
}

3、子类   

_table_pre = 'haitao_';  //默认拿config/mysql.php 中的tablepre
        $this->_redis_pre = 'haitao_for_test_';  //当前模型redis数据前缀  默认为 _table_pre

        //数据集合,必须保持此数据结构
        /*$this->_table = array(
            'mainTable' => array(
                'table' => 'abroad_goods',
                'fields' => '*',
                'name' => 'ag_id'
            ),
            'subTable' => array(
                //keyName 为子表数据在返回值中的key名称,必须
                array(
                    'table' => 'abroad_order',
                    'fields' => '*',
                    'keyName' => 'x1',
                    'name' => 'ao_ag_id',
                    'order' => 'ao_id DESC',
                    'where' => array(
                        array('name' => 'ao_goods_name', 'oper' => 'like', 'value' => ''%说法%''),
                        array('name' => 'ao_status', 'oper' => '=', 'value' => '1'),   //只查有用的数据  缓存到内存中
                    )
                ),
                array(
                    'table' => 'abroad_order',
                    'fields' => '*',
                    'keyName' => 'x2',
                    'name' => 'ao_ag_id',
                    'order' => 'ao_id DESC',
                    'where' => array(
                        array('name' => 'ao_goods_name', 'oper' => 'not like', 'value' => ''%说法%''),
                    )
                ),
            )
        );*/
        parent::__construct();
    }

    public function flashAll() {
        return parent::flashAll(); // TODO: Change the autogenerated stub
    }

}

 4、调用

flashAll();
//        $model->set(8, '----------1111----
');
        for ($i = 1; $i < 10000; $i++)
            $model->set('access_token' . $i, mt_rand(10000, 5555555));
        print_r($model->get('access_token1'));

    }

    public function setAction() {
        $model = new App_Model_Redis_RedisAbroadBannerStorage();
        $m = $model->get('access_token', false);
        print_r($m);
        print_r($model->keys('*'));

    }

    public function getAction() {
        $model = new App_Model_Redis_RedisAbroadBannerStorage();
        $model->flashAll();
        $data = $model->getTableData();

        $data['subTable'][0]['keyName'] = 'xxxx2'; //oper 缺省,则使用 =;     如果缺省value,则使用$id 作为条件;
//        print_r($data);
        $model->setTableData($data);
        $data = $model->getTableData();
//        print_r($data);
        print_r($m = $model->get(8));
    }
}



回复列表



回复操作






   

发布时间:2018-12-15 11:07:28