1. 依耐关系(首先需要安装Redis_fdw
)
关于Redis_fdw
详见:https://pgxn.org/dist/redis_fdw/
CREATE EXTENSION IF NOT EXISTS redis_fdw;
CREATE SERVER redis_server FOREIGN DATA WRAPPER redis_fdw OPTIONS (address '127.0.0.1', port '6379');
CREATE USER MAPPING FOR PUBLIC SERVER redis_server OPTIONS (password '');
2. 操作方法、使用范列
structure_redis
存储过程可以用于某个表的触发器中,或其他数据逻辑操作的存储过程中- 当数据层某个表的数据发生变化时运行该存储过程快速创建、更新或删除Redis数据,应用层不需要去操作
Redis
,只需要读取Redis
即可- 会在数据库中生成一个
"public"."police_redis_foreign"
的数据表,用于存放Redis服务器数据库MAP(0~15),请自行规划好Redis数据存放位置Redis
服务器数据库15位置处,KEY
值为indexedDBStorage_foreignList:redisForeign
存放着"public"."police_redis_foreign"
的数据表的数据,方便应用层查找调用数据Redis
的KEY
值生成规则:storage_store:pk
2.1 清空Redis
缓存
SELECT structure_redis(json_build_object(
'type', 'empty',
'foreign', '外部表名称(不指定则清空所有)',
'redis', 'police_redis(默认)'
);
2.2. 创建或刷新一条JSON
对象形式的Redis
缓存记录,用于单一数据的缓存
2.2.1 将指定表
table
的where
查询结果的第一行记录以JSON
对象形式进行Redis
数据缓存
SELECT structure_redis(
json_build_object(
'pk', 4, -- 数据主键值
'type', 'info', -- 数据类型, 必须指定为`info`
'databases', 1, -- 指定Redis的databases,范围:0~15, 默认:0
'storage', 'sessionStorage', -- 前端存储位置, 用于构造Redis的Key,默认indexedDBStorage
'store', 'userInfo', -- 前端存储store, 用于构造Redis的Key
'table', 'police_view_user', -- 数据查询表名
'where', 'uid=4' -- 数据查询条件
)
);
2.2.2 将指定表
table
的主键primary
等于pk
的查询结果的第一行记录以JSON
对象形式进行Redis
数据缓存
SELECT structure_redis(
json_build_object(
'pk', 4, -- 数据主键值
'type', 'info', -- 数据类型, 必须指定为`info`
'databases', 1, -- 指定Redis的databases,范围:0~15, 默认:0
'storage', 'sessionStorage', -- 前端存储位置, 用于构造Redis的Key,默认indexedDBStorage
'store', 'userInfo', -- 前端存储store, 用于构造Redis的Key
'table', 'police_view_user', -- 数据查询表名
'primary', 'uid' -- 查询主键列名
)
);
2.3 将指定表table
的where
查询结果以JSON
数组对象形式创建或刷新一条Redis
缓存记录,用于数据列表的缓存
SELECT structure_redis(
json_build_object(
'pk', 'policerList', -- 数据PK值(此处并非主键值,用以标注唯一性)
'type', 'list', -- 数据类型,可以不必指定,如果指定必须指定为`list`
'databases', 1, -- 指定Redis的databases,范围:0~15, 默认:0
'storage', 'indexedDBStorage', -- 前端存储位置, 用于构造Redis的Key,默认indexedDBStorage
'store', 'userList', -- 前端存储store, 用于构造Redis的Key
'table', 'police_view_user_list', -- 数据查询表名
'where', 'user_group::JSONB @> json_build_array(''police'')::JSONB' -- 数据查询条件
)
);
2.4 将指定数据data
进行Redis
数据缓存
SELECT structure_redis(
json_build_object(
'pk', 4,
'type', 'info', -- 数据类型, 必须指定为`info`
'databases', 1, -- 指定Redis的databases,范围:0~15, 默认:0
'storage', 'sessionStorage',
'store', 'userInfo',
'data', '需要进行Redis缓存的数据'
)
);
2.5 删除一条指定pk
的Redis
缓存记录
SELECT structure_redis(
json_build_object(
'pk', 4,
'storage', 'sessionStorage',
'store', 'userInfo'
)
);
3 参数说明
参数 | 参数说明 | 可选值 | 类型 | 是否必填 | 默认值 |
---|---|---|---|---|---|
type | 数据或操作类型 | list、info、remove、empty | ENUM | false | list |
schemas | 缓存分区,可用于按用户组或项目功能进行数据可见性的分区 | NULL | string | false | app |
storage | 前端本地存储方式 | NULL | string | 除完全清空Redis外均必填 | NULL |
store | 前端本地存储store名 | NULL | string | 除完全清空Redis外均必填 | NULL |
table | 缓存所需的数据库表名 | NULL | string | 缓存数据时未指定data情况下必填 | NULL |
where | 缓存所需的数据库查询方法 | NULL | string | false | NULL |
data | 所需缓存的数据 | NULL | JSON | 缓存数据时未指定table情况下必填 | NULL |
dbindex | Redis数据库ID,该缓存数据在Redis中的位置 | NULL | number | false | 0 |
pk | 当缓存列表数据时为list;当缓存info数据时为数据主键 | NULL | string or number | 缓存数据类型为info时必填 | list |
method | 数据请求方法 | get、post、put、delete、options | ENUM | false | get |
restful | RestFul请求路径 | NULL | string | 新增缓存数据时必填 | NULL |
route | 数据Route请求方式所需的参数 | NULL | JSON | false | NULL |
4. 数据表和视图
DROP TYPE IF EXISTS methods;
CREATE TYPE methods AS ENUM('get', 'post', 'put', 'delete', 'options');
DROP TYPE IF EXISTS data_type;
CREATE TYPE data_type AS ENUM('list', 'info', 'empty', 'remove');
CREATE TABLE "public"."base_redis_foreigns" (
"foreigns" VARCHAR(150) NOT NULL,
"storage" VARCHAR(50) NOT NULL,
"store" VARCHAR(50) NOT NULL,
"table" VARCHAR(200) DEFAULT NULL,
"where" VARCHAR(200) DEFAULT NULL,
"type" data_type DEFAULT 'list',
"dbindex" SMALLINT DEFAULT 0,
"numbers" INTEGER DEFAULT 0,
"datetime" TIMESTAMP(3) WITHOUT TIME ZONE NOT NULL DEFAULT now(),
PRIMARY KEY ("foreigns")
);
COMMENT ON TABLE "public"."base_redis_foreigns" IS 'Redis外部表数据';
COMMENT ON COLUMN "public"."base_redis_foreigns"."foreigns" IS 'Redis外部表名';
COMMENT ON COLUMN "public"."base_redis_foreigns"."storage" IS '前端本地存储方式';
COMMENT ON COLUMN "public"."base_redis_foreigns"."store" IS '前端本地存储store名';
COMMENT ON COLUMN "public"."base_redis_foreigns"."table" IS '数据库查询表名';
COMMENT ON COLUMN "public"."base_redis_foreigns"."where" IS '数据库查询方法';
COMMENT ON COLUMN "public"."base_redis_foreigns"."type" IS '数据缓存类型';
COMMENT ON COLUMN "public"."base_redis_foreigns"."dbindex" IS 'Redis数据库id';
COMMENT ON COLUMN "public"."base_redis_foreigns"."numbers" IS '数据缓存数量';
COMMENT ON COLUMN "public"."base_redis_foreigns"."datetime" IS '最后更新时间';
CREATE TABLE "public"."base_redis_map" (
"id" SERIAL8,
"key" VARCHAR(150) NOT NULL,
"foreigns" VARCHAR(150) NOT NULL,
"method" methods DEFAULT 'get',
"restful" VARCHAR(200) DEFAULT NULL,
"route" JSON DEFAULT NULL,
"datetime" TIMESTAMP(3) WITHOUT TIME ZONE NOT NULL DEFAULT now(),
PRIMARY KEY ("id")
);
COMMENT ON TABLE "public"."base_redis_map" IS 'Redis数据请求方式MAP';
COMMENT ON COLUMN "public"."base_redis_map"."id" IS '自增主键';
COMMENT ON COLUMN "public"."base_redis_map"."key" IS 'Redis缓存KEY键名';
COMMENT ON COLUMN "public"."base_redis_map"."foreigns" IS 'Redis外部表名';
COMMENT ON COLUMN "public"."base_redis_map"."method" IS '数据请求方式';
COMMENT ON COLUMN "public"."base_redis_map"."restful" IS '数据请求RestFul路径';
COMMENT ON COLUMN "public"."base_redis_map"."route" IS '数据请求Route方式参数';
COMMENT ON COLUMN "public"."base_redis_map"."datetime" IS '最后更新时间';
DROP VIEW IF EXISTS "public"."base_redis_map_view";
CREATE VIEW "public"."base_redis_map_view" AS
SELECT
M."key",
M."foreigns",
F."storage",
F."store",
F."table",
F."where",
F."type",
F."dbindex",
F."numbers",
M."method",
M."restful",
M."route"
FROM "public"."base_redis_map" AS M, "public"."base_redis_foreigns" AS F
WHERE M.foreigns = F.foreigns;
5. 存储过程
CREATE OR REPLACE FUNCTION structure_redis(
IN redis JSON
)RETURNS JSON
AS $$
DECLARE
redis_table_schemas VARCHAR(50) := 'public'; -- 请自行根据实际情况配置数据库的schemas
redis_table_prefix VARCHAR(50) := 'police'; -- 请自行根据实际情况配置数据库表名前缀
redis_table_name VARCHAR(50) := 'redis_foreign'; -- 请自行根据实际情况配置数据库表名
redis_table VARCHAR(150);
pk_val VARCHAR(100);
storage_val VARCHAR(50);
store_val VARCHAR(50);
redis_key VARCHAR(100);
foreign_table VARCHAR(100) DEFAULT NULL;
foreign_table_array VARCHAR(100)[];
table_val VARCHAR(100) DEFAULT NULL;
where_val VARCHAR(250) DEFAULT NULL;
type_val VARCHAR(50) DEFAULT 'list';
redis_table_num INTEGER;
foreign_table_num INTEGER;
redis_key_num INTEGER;
databases SMALLINT DEFAULT 0;
executesql TEXT;
data_val JSON DEFAULT NULL;
BEGIN
IF (json_extract_path_text(redis, 'type') IS NOT NULL) THEN
type_val := json_extract_path_text(redis, 'type');
END IF;
IF (json_extract_path_text(redis, 'redis') IS NOT NULL) THEN
redis_table := json_extract_path_text(redis, 'redis');
END IF;
IF (json_extract_path_text(redis, 'foreign') IS NOT NULL) THEN
foreign_table := lower(json_extract_path_text(redis, 'foreign'));
END IF;
redis_table := '"'||redis_table_schemas||'"."'||redis_table_prefix||'_'||redis_table_name||'"';
SELECT COUNT(*) INTO redis_table_num FROM information_schema.tables WHERE table_type = 'BASE TABLE' AND table_name = redis_table_prefix||'_'||redis_table_name;
IF(redis_table_num = 0) THEN
executesql := 'CREATE TABLE '||redis_table||' (' ||
'"foreigns" VARCHAR(150) NOT NULL,' ||
'"storage" VARCHAR(50) NOT NULL,' ||
'"store" VARCHAR(50) NOT NULL,' ||
'"tables" VARCHAR(200) DEFAULT NULL,' ||
'"databases" SMALLINT DEFAULT 0,' ||
'"numbers" INTEGER DEFAULT 0,' ||
'"datetime" TIMESTAMP(3) WITHOUT TIME ZONE NOT NULL DEFAULT now(),' ||
'PRIMARY KEY ("foreigns")'
');' ||
'COMMENT ON TABLE ' || redis_table || ' IS ''开发日志记录'';' ||
'COMMENT ON COLUMN ' || redis_table || '."foreigns" IS ''Redis外部表名'';' ||
'COMMENT ON COLUMN ' || redis_table || '."storage" IS ''前端本地存储方式'';' ||
'COMMENT ON COLUMN ' || redis_table || '."store" IS ''前端本地存储store名'';' ||
'COMMENT ON COLUMN ' || redis_table || '."tables" IS ''数据库查询表名'';' ||
'COMMENT ON COLUMN ' || redis_table || '."databases" IS ''Redis数据库id'';' ||
'COMMENT ON COLUMN ' || redis_table || '."numbers" IS ''数据缓存数量'';' ||
'COMMENT ON COLUMN ' || redis_table || '."datetime" IS ''最后更新时间'';';
EXECUTE executesql;
END IF;
IF(lower(type_val) = 'empty') THEN
IF(foreign_table IS NULL) THEN
SELECT array_agg(table_name::VARCHAR) INTO foreign_table_array FROM information_schema.tables WHERE table_type = 'FOREIGN TABLE' AND table_name LIKE 'redis_%';
IF(foreign_table_array IS NOT NULL) THEN
FOREACH foreign_table IN ARRAY foreign_table_array
LOOP
executesql := 'DELETE FROM '||redis_table||' WHERE foreigns = $1;';
EXECUTE executesql USING foreign_table;
executesql := 'DELETE FROM "' || foreign_table || '";';
EXECUTE executesql;
executesql := 'DROP FOREIGN TABLE IF EXISTS "' || foreign_table || '";';
EXECUTE executesql;
END LOOP;
END IF;
executesql := 'DROP TABLE '||redis_table||';';
EXECUTE executesql USING foreign_table;
RETURN json_build_object('type', 'Success', 'message', '服务器中所有的Redis缓存已经被清空!', 'code', 200);
ELSE
executesql := 'DELETE FROM '||redis_table||' WHERE foreigns = $1;';
EXECUTE executesql USING foreign_table;
executesql := 'DELETE FROM "' || foreign_table || '";';
EXECUTE executesql;
executesql := 'DROP FOREIGN TABLE IF EXISTS "' || foreign_table || '";';
EXECUTE executesql;
RETURN json_build_object('type', 'Success', 'message', '服务器中【' || foreign_table || '】的Redis缓存已经被清空!', 'code', 200);
END IF;
ELSE
IF (json_extract_path_text(redis, 'pk') IS NOT NULL) THEN
pk_val := json_extract_path_text(redis, 'pk');
ELSE
RETURN json_build_object('type', 'Error', 'message', 'Redis缓存pk参数不能为空!', 'code', 230);
END IF;
IF (json_extract_path_text(redis, 'storage') IS NOT NULL) THEN
storage_val := json_extract_path_text(redis, 'storage');
ELSE
RETURN json_build_object('type', 'Error', 'message', 'Redis缓存storage参数不能为空!', 'code', 230);
END IF;
IF (json_extract_path_text(redis, 'store') IS NOT NULL) THEN
store_val := json_extract_path_text(redis, 'store');
ELSE
RETURN json_build_object('type', 'Error', 'message', 'Redis缓存store参数不能为空!', 'code', 230);
END IF;
IF (json_extract_path_text(redis, 'table') IS NOT NULL) THEN
table_val := json_extract_path_text(redis, 'table');
END IF;
IF (json_extract_path_text(redis, 'primary') IS NOT NULL) THEN
where_val := json_extract_path_text(redis, 'primary') || ' = ' || pk_val;
ELSE
IF (json_extract_path_text(redis, 'where') IS NOT NULL) THEN
where_val := json_extract_path_text(redis, 'where');
END IF;
END IF;
IF (json_extract_path_text(redis, 'data') IS NOT NULL) THEN
data_val := json_extract_path_text(redis, 'data');
END IF;
IF (json_extract_path_text(redis, 'databases') IS NOT NULL) THEN
databases := json_extract_path_text(redis, 'databases');
END IF;
IF(foreign_table IS NULL) THEN
foreign_table := 'redis_' || storage_val || '_' || store_val;
END IF;
SELECT COUNT(*) INTO foreign_table_num FROM information_schema.tables WHERE table_type = 'FOREIGN TABLE' AND table_name = foreign_table;
if(foreign_table_num = 0) THEN
executesql := 'CREATE FOREIGN TABLE "' || foreign_table || '" ("key" text, "val" json) SERVER redis_server OPTIONS ( database ''' || databases || ''');';
EXECUTE executesql;
executesql := 'INSERT INTO '||redis_table||' ("foreigns", "storage", "store", "tables", "databases") VALUES($1, $2, $3, $4, $5);';
EXECUTE executesql USING foreign_table, storage_val, store_val, table_val, databases;
ELSE
executesql := 'SELECT databases FROM '||redis_table||' WHERE foreigns = $1;';
EXECUTE executesql INTO databases USING foreign_table;
END IF;
redis_key := storage_val || '_' || store_val || ':' || pk_val;
executesql := 'SELECT COUNT(*) FROM "' || foreign_table || '" WHERE "key" = $1;';
EXECUTE executesql INTO redis_key_num USING redis_key;
IF (table_val IS NULL AND where_val IS NULL AND data_val IS NULL) THEN
IF (redis_key_num > 0) THEN
executesql := 'UPDATE "'||redis_table||' SET numbers = numbers - 1, datetime = now() WHERE foreigns = $1;';
EXECUTE executesql USING foreign_table;
executesql := 'DELETE FROM "' || foreign_table || '" WHERE "key" = $1;';
EXECUTE executesql USING redis_key;
IF(pk_val != 'redisForeign') THEN
PERFORM structure_redis(json_build_object(
'pk', 'redisForeign',
'databases', 15,
'storage', 'indexedDBStorage',
'store', 'foreignList',
'table', redis_table_prefix||'_'||redis_table_name
));
END IF;
RETURN json_build_object('type', 'Success', 'message', '删除Redis缓存['||redis_key||']成功!', 'databases', databases, 'code', 230);
ELSE
RETURN json_build_object('type', 'Error', 'message', '未发现['||redis_key||']的Redis缓存!', 'code', 230);
END IF;
ELSE
IF(table_val IS NULL AND data_val IS NULL)THEN
RETURN json_build_object('type', 'Error', 'message', 'Redis缓存table参数和data参数不能同时为空!', 'code', 230);
ELSE
IF (table_val IS NOT NULL) THEN
IF(where_val IS NULL) THEN
IF(lower(type_val) = 'info') THEN
executesql := 'SELECT json_agg(' || table_val || ')->0 FROM "' || table_val || '" LIMIT 1;';
ELSE
executesql := 'SELECT json_agg(' || table_val || ') FROM "' || table_val || '";';
END IF;
ELSE
IF(lower(type_val) = 'info') THEN
executesql := 'SELECT json_agg(' || table_val || ')->0 FROM "' || table_val || '" WHERE ' || where_val || ' LIMIT 1;';
ELSE
executesql := 'SELECT json_agg(' || table_val || ') FROM "' || table_val || '" WHERE ' || where_val || ';';
END IF;
END IF;
EXECUTE executesql INTO data_val;
END IF;
END IF;
IF(lower(type_val) = 'list') THEN
IF(data_val IS NULL) THEN
data_val := json_build_array();
END IF;
ELSE
IF(data_val IS NULL) THEN
data_val := json_build_object();
END IF;
END IF;
IF (redis_key_num > 0) THEN
executesql := 'UPDATE "' || foreign_table || '" SET "val" = $1 WHERE "key" = $2;';
EXECUTE executesql USING data_val, redis_key;
executesql := 'UPDATE '|| redis_table || ' SET datetime = now() WHERE foreigns = $1;';
EXECUTE executesql USING foreign_table;
IF(pk_val != 'redisForeign') THEN
PERFORM structure_redis(json_build_object(
'pk', 'redisForeign',
'databases', 15,
'storage', 'indexedDBStorage',
'store', 'foreignList',
'table', redis_table_prefix||'_'||redis_table_name
));
END IF;
RETURN json_build_object(
'type', 'Success',
'message', '更新Redis缓存['||redis_key||']成功!',
'code', 200,
'debug', json_build_object(
'pk', pk_val,
'table', table_val,
'where', where_val
),
'redis', json_build_array(
json_build_object(
'pk', pk_val,
'databases', databases,
'storage', storage_val,
'store', store_val,
'table', store_val,
'type', type_val,
'key', redis_key
)
)
);
ELSE
executesql := 'INSERT INTO "' || foreign_table || '" ("key", "val") VALUES ($1, $2);';
EXECUTE executesql USING redis_key, data_val;
executesql := 'UPDATE '||redis_table||' SET numbers = numbers + 1, datetime = now() WHERE foreigns = $1;';
EXECUTE executesql USING foreign_table;
IF(pk_val != 'redisForeign') THEN
PERFORM structure_redis(json_build_object(
'pk', 'redisForeign',
'databases', 15,
'storage', 'indexedDBStorage',
'store', 'foreignList',
'table', redis_table_prefix||'_'||redis_table_name
));
END IF;
RETURN json_build_object(
'type', 'Success',
'message', '添加Redis缓存['||redis_key||']成功!',
'code', 230,
'debug', json_build_object(
'pk', pk_val,
'table', table_val,
'where', where_val
),
'redis', json_build_array(
json_build_object(
'pk', pk_val,
'databases', databases,
'storage', storage_val,
'store', store_val,
'table', store_val,
'type', type_val,
'key', redis_key
)
)
);
END IF;
END IF;
END IF;
EXCEPTION WHEN OTHERS THEN
RETURN json_build_object('type', 'Error', 'message', '系统Redis缓存操作失败!', 'error', replace(SQLERRM, '"', '`'), 'sqlstate', SQLSTATE);
END;
$$ LANGUAGE plpgsql;
4. 基于ThinkPHP 5.1
的 Redis
操作模型
A. 调用方法
A.1 清空所有
Redis
数据
$redisData = model\Base::structureRedis(['type' => 'empty']);
A.2 删除指定
Redis
的KEY
数据
删除
KEY
为sessionStorage_userInfo:5
的Redis
数据$redisData = model\Base::structureRedis([ 'pk' => 5, 'type' => 'empty', 'storage' => 'sessionStorage', 'store' => 'userInfo' ]);
A.3 获取指定
Redis
数据,如果不存在则根据table
和where
创建Redis
数据
获取
KEY
值为sessionStorage_userInfo:5
的Redis
数据,如果该数据不存在则根据table
和where
创建Redis
数据$return = model\Base::structureRedis([ 'pk' => 5, 'type' => 'info', 'databases' => 1, 'storage' => 'sessionStorage', 'store' => 'userInfo', 'table' => 'public_user', 'where' => 'uid = 5' ]);
A.4 获取指定
Redis
数据,如果不存在则根据table
和primary
创建Redis
数据
获取
KEY
值为sessionStorage_userInfo:5
的Redis
数据,如果该数据不存在则根据table
和primary
创建Redis
数据$return = model\Base::structureRedis([ 'pk' => 5, 'type' => 'info', 'databases' => 1, 'storage' => 'sessionStorage', 'store' => 'userInfo', 'table' => 'public_user', 'primary' => 'uid' ]);
A.5 获取指定
Redis
数据,强制根据table
和primary
创建Redis
数据
强制根据
table
和primary
创建Redis
数据后, 返回KEY
值为sessionStorage_userInfo:5
的Redis
数据$return = model\Base::structureRedis([ 'pk' => 5, 'type' => 'info', 'databases' => 1, 'storage' => 'sessionStorage', 'store' => 'userInfo', 'table' => 'public_user', 'where' => 'uid = 5' ], true);
B. 程序代码
namespace app\redis\model;
use think\Model;
use think\Db;
class Base extends Model{
/**
* # 数组数据按条件筛选方法
* @param $array 待筛选的数组
* @param $filter 筛选条件: ['key' => '筛选键值名', 'val' => '筛选值', 'operator' => '筛选运算符']
* @return mixed 返回匹配的数组值
*/
protected static function arrayFilter($array, $filter){
$filter = array_filter($array, function($val) use ($filter){
switch($filter['operator']){
case 'regexp':
return preg_match($filter['val'], $val[$filter['key']]);
case 'between':
return $val[$filter['key']] >= $filter['val'][0] && $val[$filter['key']] <= $filter['val'][1];
case '<':
return $val[$filter['key']] < $filter['val'];
case '<=':
return $val[$filter['key']] <= $filter['val'];
case '>':
return $val[$filter['key']] > $filter['val'];
case '>=':
return $val[$filter['key']] >= $filter['val'];
case '=':
default:
return $val[$filter['key']] == $filter['val'];
}
});
foreach(array_keys($filter) as $v){
$return[] = $filter[$v];
}
return $return;
}
/**
* # 运行数据库存储过程
* @param $name 存储过程名
* @param array $param 存储过程参数数组或字符串
* @param string $type 数据链接类型,默认:thinkphp,可选:adodb
* @return mixed
*/
protected static function callProcedure($name, $param = array(), $type = 'thinkphp'){
if($type == 'adodb'){
$db_conf = config('database.');
$db = ADONewConnection($db_conf['type']);
$db->Connect($db_conf['hostname'], $db_conf['username'], $db_conf['password'], $db_conf['database']);
$db->setFetchMode(ADODB_FETCH_ASSOC);
if(is_array($param))
$logic = $db->getAll("SELECT ".$name."('".json_encode($param)."');");
else
$logic = $db->getAll("SELECT ".$name."('".$param."');");
}else{
if(is_array($param))
$logic = Db::query("SELECT ".$name."('".json_encode($param)."');");
else
$logic = Db::query("SELECT ".$name."('".$param."');");
}
return json_decode($logic[0][$name], true);
}
/**
* # 链接Redis服务器
* @param int $dbindex 链接数据库index,默认:0,范围:0~15
* @return \Redis
*/
protected static function connectRedis($dbindex = 0){
$redis = new \Redis();
$conf = config('redis.');
$redis->connect($conf['host'], $conf['port'], $conf['timeout']);
$redis->auth($conf['password']);//登录验证密码,返回【true | false】
$redis->select($dbindex);
return $redis;
}
/**
* # 操作redis方法
* @param $param 操作参数
* @param bool $refresh 是否强制刷新
* @return array|mixed
*/
public static function structureRedis($param, $refresh = false){
if(array_key_exists('storage', $param) && array_key_exists('store', $param)){
$redis = self::connectRedis(15);
$map = $redis->get('indexedDBStorage_foreignList:redisForeign');
$filter = self::arrayFilter(json_decode($map, true), ['key' => 'foreigns', 'val' => 'redis_'.$param['storage'].'_'.$param['store']]);
if(count($filter[0]) > 0){
$foreign = array_merge($param, $filter[0]);
if(array_key_exists('tables', $foreign)) $foreign['table'] = $foreign['tables'];
}else{
$foreign = $param;
$foreign['databases'] = (array_key_exists('databases', $param))?$param['databases']:0;
}
$redis = self::connectRedis($foreign['databases']);
if(array_key_exists('pk', $foreign)){
$key = $foreign['storage'].'_'.$foreign['store'].':'.$foreign['pk'];
}else{
if(array_key_exists('key', $foreign)){
$key = $foreign['key'];
}else{
return ['type' => 'Error', 'message' => '参数不正确,缺少pk或者key参数', 'param' => $foreign];
}
}
if(!$redis->get($key) || $refresh){
if(array_key_exists('table', $foreign) || array_key_exists('data', $foreign)){
$logic = self::callProcedure('structure_redis', $foreign);
if(strtolower($logic['type']) == 'error') return $logic;
}else{
return ['type' => 'Error', 'message' => '参数不正确,缺少table或者data参数', 'param' => $foreign];
}
}
return json_decode($redis->get($key), true);
}else{
if(array_key_exists('type', $param) && $param['type'] == 'empty'){
$logic = self::callProcedure('structure_redis', $param);
return json_decode($logic, true);
}else{
return ['type' => 'Error', 'message' => '参数不正确,缺少storage或者store参数', 'param' => $param];
}
}
}
}