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里缓存相关类库的修改的主要内容,如果未能解决你的问题,请参考以下文章

php 碳类库的相关代码

php laravel管理员相关类库

php laravel类库相关

PHP 类库的使用

PHP 类库的使用

PHP 类库的使用