【PHP】Yii2的Cache组件cachePath遇到的坑,亲测可用
💪 日拱一卒无有尽,功不唐捐终入海
👀 关注收藏不迷路,早晚都能成大神
业务需求
由于业务需要,用户登录之后,我需要判断用户是否为违禁用户组,如果是,就要主动退出登录。
基本流程为
- 进入页面
- 判断用户组
- 退出登录
实现细节
实现具体在判断用户组,由于项目涉及到的Action众多,我就把处理用户组的调用放在了Controller里。
代码为
class SiteController extends Controller
{
    public function beforeAction($action)
    {
            $loginuid = Yii::$app->user->getId();
            if($loginuid && XXXX::checkUserRight($loginuid, coderfix.blog.csdn.net::INTER_FORCE_LOGOUT)){
            Yii::$app->user->logout();
        }
        return parent::beforeAction($action);
    }
}
  
 - 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
checkUserRight代码为
    /**
     * 判断用户是否拥有对应的权限
     * @param $uid
     * @param $action
     * @return bool | array
     */
    public static function checkUserRight($uid,$action = null){
        $cache = Yii::$app->cache;
        $key = 'coderfix.blog.csdn.net'.$uid;
        $alias = '@coderfix.blog.csdn.net/runtime/cache';
        $cache->cachePath = \Yii::getAlias($alias);
        $rights = $cache->getOrSet($key, function ()use ($uid) {
			//具体业务查询用户组以及对应权限
        },Yii::$app->params['CacheDuration']);
        $cache->cachePath = $cachePath;
        if($action && isset($rights[$action])){
            return $rights[$action];
        }
        return $rights;
    }
  
 - 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
Bug描述
这个项目有多个内部app组成,一个主页生成的缓存之后,另一个主页直接获取对应的缓存,并没有调用业务逻辑,生成自己页面的缓存。
分析原因
先抛出根本原因:
由于页面执行的页面缓存pageCache使用了其他app的首页缓存,他们的缓存路径被设置成了同一个,并且因为都是主页,所以缓存计算的key是一致的,导致加载缓存位置一致。
详细代码
在checkUserRight阶段,设置了cachePath
$cache = Yii::$app->cache; 
$cache->cachePath = \Yii::getAlias($alias); //这里
  
 - 1
- 2
- 3
由于Yii2的实例是单例模式,一次运行中的Yii对象一直维持一个,所以我在检测权限步骤拿缓存的时候,设置的缓存路径一直生效。
而且Controller中beforeAction的方法在整个生命周期的前面
就导致了后面页面缓存pageCache调用的Cache组件的缓存路径被固定
根据Yii2项目源码vendor/yiisoft/yii2/filters/PageCache.php中计算key的方法
    /**
     * @return array the key used to cache response properties.
     * @since 2.0.3 coderfix.blog.csdn.net
     */
    protected function calculateCacheKey()
    {
        $key = [__CLASS__];
        if ($this->varyByRoute) {
            $key[] = Yii::$app->requestedRoute;
        }
        return array_merge($key, (array)$this->variations);
    }
  
 - 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
得到的key就是一致的。
解决方案
临时使用缓存组件,设置cachePath之后,使用完成之后,再把之前值改回去。
		$cache = Yii::$app->cache;
        $cachePath = $cache->cachePath;
        $key = 'coderfix.blog.csdn.net'.$uid;
        $alias = '@coderfix.blog.csdn.net/runtime/cache';
        $cache->cachePath = \Yii::getAlias($alias);
        //这里执行缓存操作逻辑
        $cache->cachePath = $cachePath;
  
 - 1
- 2
- 3
- 4
- 5
- 6
- 7
🏃♂️ 好记性不如烂笔头,收藏本文吧!技术求知路好走💼!
文章来源: coderfix.blog.csdn.net,作者:小雨青年,版权归原作者所有,如需转载,请联系作者。
原文链接:coderfix.blog.csdn.net/article/details/118197398
- 点赞
- 收藏
- 关注作者
 
             
           
评论(0)