php laravel里缓存相关类库的修改
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了php laravel里缓存相关类库的修改相关的知识,希望对你有一定的参考价值。
# laravel里cache的覆盖修改
## Cache.php
Cache的Facade
## CacheServiceProvider.php
通过provider修改系统cache
## SysCacheManager.php
覆盖系统cache的类
## CacheMulti.php
缓存多个key的子类
# laravel里redis的覆盖修改
## RedisServiceProvider
通过provider修改系统的RedisManager
## app.providers
添加\App\Providers\RedisServiceProvider::class
<?php
/**
* Created by PhpStorm.
* User: code
* Date: 2018/9/28
* Time: 上午10:32
*/
namespace App\Repositories\Common;
use Illuminate\Support\Facades\Cache;
class CacheMulti extends CacheMultiAbstract
{
protected function setCachePro($key, $value, $minutes)
{
return Cache::put($key, $value, $minutes);
}
protected function getCachePro($key)
{
return Cache::get($key);
}
}
<?php
/**
* Created by PhpStorm.
* User: code
* Date: 2018/4/13
* Time: 上午11:08
*/
namespace App\Repositories\Common\Facades;
/**
* Cache的Facade
*
* put是set的意思
*
* @method static mixed remember($key, $minutes, \Closure $callback) 写入
* @method static bool forget($key) 删除
* @method static string getCacheKey(...$keys) 组织缓存key
*
* @mixin \App\Repositories\Common\Vendor\Laravel\SysCacheManager
*/
class Cache extends \Illuminate\Support\Facades\Cache
{
}
<?php
namespace App\Providers;
use App\Repositories\Common\Vendor\Laravel\SysCacheManager;
/**
* 修改系统cache
*
* @since 2018/4/13
* @package App\Providers
*/
class CacheServiceProvider extends \Illuminate\Cache\CacheServiceProvider
{
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
parent::register();
$this->app->singleton('cache', function ($app){
return new SysCacheManager($app);
});
}
}
<?php
/**
* Created by PhpStorm.
* User: code
* Date: 2018/4/13
* Time: 上午10:59
*/
namespace App\Repositories\Common\Vendor\Laravel;
use App\Repositories\Common\CacheMulti;
use Closure;
use Illuminate\Cache\CacheManager;
/**
* SysCacheManager
*
* @method static remember(...$args)
*
* // 解决mixin
* @method bool set($key, $value, $ttl = null)
* @method bool delete($key)
* @method bool clear()
* @method iterable getMultiple($keys, $default = null)
* @method bool setMultiple($values, $ttl = null)
* @method bool deleteMultiple($keys)
* @method bool has($key)
* @method mixed pull($key, $default = null)
* @method void put($key, $value, $minutes)
* @method bool add($key, $value, $minutes)
* @method int|bool increment($key, $value = 1)
* @method int|bool decrement($key, $value = 1)
* @method void forever($key, $value)
* @method mixed sear($key, Closure $callback)
* @method mixed rememberForever($key, Closure $callback)
* @method bool forget($key)
* @method \Illuminate\Contracts\Cache\Store getStore()
*/
class SysCacheManager extends CacheManager
{
use CachePutAndAddTimeTrait;
public static function getCacheKey(...$keys)
{
return join($keys, ':');
}
public static function cacheMulti($prefix, $minutes, array $data, callable $func, $emptyDefault = null)
{
return CacheMulti::instance()->cacheMulti($prefix, $minutes, $data, $func, $emptyDefault);
}
}
<?php
/**
* Created by PhpStorm.
* User: code
* Date: 2018-12-25
* Time: 14:41
*/
namespace App\Repositories\Common\Vendor\Laravel;
trait CachePutAndAddTimeTrait
{
/**
* 写入数据,并添加key的缓存时间
*
* @param $key
* @param $value
* @param $minutes
*/
public function putAndAddTime($key, $value, $minutes)
{
$this->put($key, $value, $minutes);
// 写入缓存时间
$this->put($this->handleAddTimeCacheKey($key), time(), $minutes);
}
/**
* 获取缓存的时间,根据putAddTime
* 返回时间戳
*
* @param $key
* @param bool $default
* @return int|false
*/
public function getAddTime($key, $default = false)
{
return $this->store()->get($this->handleAddTimeCacheKey($key), $default);
}
protected function handleAddTimeCacheKey($key)
{
return $key . ':time';
}
}
<?php
/**
* Created by PhpStorm.
* User: code
* Date: 2019-01-07
* Time: 13:47
*/
namespace App\Repositories\Common\Vendor\Laravel;
/**
* 将获取和保存放一起用于统一入口,和减少方法数量
*/
trait RedisTimeBoolTrait
{
/**
* 是否在时间内已经有过一次访问
*
* @param $key
* @param int $expire 时间,增加的时间(非时间戳)
* @return bool
*/
public function ifInTime($key, $expire)
{
$time = $this->get($key);
$value = time() + $expire;
if ($time && $time > $value){ // 存在
return true;
}
// predis的使用
return !!$this->set($key, $value, 'EX', $expire, 'NX'); // 返回是否存在
}
/**
* 返回时间内的次数,
* 需要等$time时间后才会重新计数
*
* @param $key
* @param int $time 设置的过期时间
* @param bool $incBool 是否设置,false就只返回次数
* @return mixed
*/
public function getIncTimeNum($key, $time, $incBool = true)
{
if ($incBool){
$this->multi();
$this->incr($key);
$this->expire($key, $time);
$exec = $this->exec();
}else{
return $this->get($key);
}
return $exec[0];
}
/**
* 返回时间内的次数,
* 在key限制的并发不高的情况下(允许雪崩的情况),提高用户体验,这样就是算第一次之后的$time时间
*
* @param $key
* @param int $time 设置的过期时间
* @param bool $incBool 是否设置,false就只返回次数
* @return mixed
*/
public function getExistsIncTimeNum($key, $time, $incBool = true)
{
if ($incBool){ // 显示
if ($this->exists($key)) { // key限制的并发不会太高的情况下
$incNum = $this->incr($key);
}else{
$this->multi();
$this->incr($key);
$this->expire($key, $time);
$exec = $this->exec();
$incNum = $exec[0];
}
}else{
return $this->get($key);
}
return $incNum;
}
/**
* 返回时间内的次数,
* 在key限制的并发不高的情况下(允许雪崩的情况),提高用户体验,这样就是算第一次之后的$time时间
*
* 通过hashes来实现,减少key
*
* @param $key
* @param $fileKey
* @param int $time 设置的过期时间
* @param bool $incBool 是否设置,false就只返回次数
* @return mixed
*/
public function getExistsHIncTimeNum($key, $fileKey, $time, $incBool = true)
{
if ($incBool){ // 显示
if ($this->exists($key)) { // key限制的并发不会太高的情况下
$incNum = $this->hincrby($key, $fileKey, 1);
}else{
$this->multi();
$this->hincrby($key, $fileKey, 1);
$this->expire($key, $time);
$exec = $this->exec();
$incNum = $exec[0];
}
}else{
return $this->hget($key, $fileKey);
}
return $incNum;
}
public function getHIncTimeNum($key, $fileKey, $time, $incBool = true)
{
if ($incBool){ // 显示
$this->multi();
$this->hincrby($key, $fileKey, 1);
$this->expire($key, $time);
$exec = $this->exec();
$incNum = $exec[0];
}else{
return $this->hget($key, $fileKey);
}
return $incNum;
}
/**
* 获取大于或等于$time的时间
*
* @param $key
* @param $expire
* @param int $step 步进
* @param int $time 时间
* @return int
*/
public function getGtTime($key, $expire, $step = 1, $time = null)
{
return $this->eval(<<<LUA
local data = redis.call("GET", ARGV[1])
if (data and data >= ARGV[3]) then
-- get数据大就自动加step的值
redis.call("SET", ARGV[1], data + ARGV[4])
return data + 1
else
redis.call("SET", ARGV[1], ARGV[3])
-- 设置过期
if (not data) then
redis.call("EXPIRE", ARGV[1], ARGV[2])
end
return ARGV[3]
end
LUA
, 0, $key, $expire, $time ?? time(), $step);
}
/**
* 通过zadd实现
* 根据指定的$currentTime时间,判断$diffTime时间内请求超过$num次,就返回true,
*
* $args为扩展函数,
* > expire 缓存过期时间
* > currentTime 指定时间,存储时可以不传,获取时就可以查询指定时间内是否超过$num次
* > value 保存zadd的值,要保证唯一性,避免覆盖
*
* > num 次数限制
*
* @param string $key 缓存的key
* @param int $diffTime 多少时间内
* @param bool $countBool 是否查询
* @param array $args
* @return bool
*/
public function getZAddTimingNum($key, $diffTime, $countBool = false, $args = [])
{
// 毫秒解决第一次回复
$currentTime = $args['currentTime'] ?: str_replace('.', '', microtime()); // 指定时间,存储时可以不传,获取时就可以查询指定时间内是否超过$num次
$options = ['WITHSCORES' => true];
$num = $args['num'] ?: 0; // 次数限制
if (!empty($num)) {
$options['LIMIT'] = [0, $num + 1];
}
if (!$countBool){
$value = $args['value'] ?: uniqid($currentTime, true);
$this->multi();
$this->zadd($key, [$value => $currentTime]);
$this->expire($key, $args['expire'] ?: $diffTime); // 缓存过期时间
$this->zrangebyscore($key, $currentTime - $diffTime, $currentTime + $diffTime, $options);
$exec = $this->exec();
$data = $exec[2];
}
$data = $data ?? $this->zrangebyscore($key, $currentTime - $diffTime, $currentTime + $diffTime, $options);
$firstTime = null;
$i = 0;
foreach ($data as $item) {
if (is_null($firstTime)){
$firstTime = $item;
// 允许第一个
if ($firstTime == $currentTime){ // 如果相同的比较多就会返回多个
return false;
}
}
if ($firstTime + $diffTime < $item) {
break;
}else{
++$i;
}
}
return $i > $num;
}
}
<?php
/**
* Created by PhpStorm.
* User: code
* Date: 2019-01-07
* Time: 14:26
*/
namespace App\Repositories\Common\Vendor\Laravel;
/** @noinspection PhpHierarchyChecksInspection */
class RedisManager extends \Illuminate\Redis\RedisManager
{
use RedisTimeBoolTrait,
RedisHelperTrait;
protected $callConnection;
/**
* 解决call只有默认connection的情况
*
* @param null $name
* @return \Illuminate\Redis\Connections\Connection
*/
public function connection($name = null)
{
$name = $name ?? $this->callConnection;
return parent::connection($name);
}
/**
* 解决connection不返回当前对象的问题
*
* @param mixed $callConnection
* @return RedisManager
*/
public function setCallConnection($callConnection)
{
$manage = clone $this;
$manage->callConnection = $callConnection;
return $manage;
}
}
<?php
/**
* Created by PhpStorm.
* User: code
* Date: 2019-01-07
* Time: 14:21
*/
namespace App\Providers;
use App\Repositories\Common\Vendor\Laravel\RedisManager;
class RedisServiceProvider extends \Illuminate\Redis\RedisServiceProvider
{
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
parent::register();
$this->app->singleton('redis', function ($app) {
$config = $app->make('config')->get('database.redis', []);
return new RedisManager($app, \Illuminate\Support\Arr::pull($config, 'client', 'predis'), $config);
});
}
}
<?php
/**
* Created by PhpStorm.
* User: code
* Date: 2019/5/9
* Time: 11:13
*/
namespace App\Helper\Vendor\Laravel;
/** @noinspection PhpHierarchyChecksInspection */
/**
* @mixin \App\Helper\Vendor\Laravel\RedisManager
*/
class Redis extends \Illuminate\Support\Facades\Redis
{
}
<?php
/**
* Created by PhpStorm.
* User: code
* Date: 2019/5/9
* Time: 20:49
*/
namespace App\Helper\Vendor\Laravel;
/**
* redis扩展方法
*/
trait RedisHelperTrait
{
/**
* hash改名,后遍历所有在删除
*
* @param int $count 一次获取的数量
* @param callable $func 回调函数,第一个参数为hash的数据
* @param string $suffix 后缀,可以传时间戳过来,这样每次rename都会不同
* @param int $i 递归用,对应scan的游标
* @param string $newKey 递归用,对应rename的新key
* @return true
*/
public function hScanRename($count, callable $func, $suffix = 'temp', $i = 0, $newKey = '')
{
recursion:;
if (!$newKey) { // 改名,后遍历所有在删除
$key = 'user:statistics:integer:hash';
if (!$this->exists($key)) { // 解决报错
return true;
}
$newKey = $key . ':' . $suffix;
$this->rename($key, $newKey);
}
$key = $newKey;
$data = $this->hscan($key, $i, [
'count' => $count,
]);
call_user_func($func, $data[1]);
if (empty($data[0]) && $i >= $data[0]) { // 没有数据时
$this->del([$newKey]);
return true;
}
$i = $data[0];
goto recursion;
}
}
以上是关于php laravel里缓存相关类库的修改的主要内容,如果未能解决你的问题,请参考以下文章