Yii中Flash数据的处理机制(源码分析)

    Flash数据是一种特别的session数据,它一旦在某个请求中设置后, 只会在下次请求中有效,然后该数据就会自动被删除。 常用于实现只需显示给终端用户一次的信息, 如用户提交一个表单后显示确认信息。

    在实际应用中,通过

$session = Yii::$app->session;
$session->setFlash("pwd","123456");

来创建一个flash数据。
$session->getFlash("pwd")

当我们获取其值以后,发现,仅仅第一次获取能获取到,第二次获取就变为空了。
那么其原理是什么呢?我们一起来分析一下:
如果直接点开,getFlash()方法:
public function getFlash($key, $defaultValue = null, $delete = false)
{
    $counters = $this->get($this->flashParam, []);
    if (isset($counters[$key])) {
        $value = $this->get($key, $defaultValue);
        if ($delete) {
            $this->removeFlash($key);
        } elseif ($counters[$key] < 0) {
            // mark for deletion in the next request
            $counters[$key] = 1;
            $_SESSION[$this->flashParam] = $counters;
        }

        return $value;
    } else {
        return $defaultValue;
    }
}

    我们会发现,有个默认的$delete参数,但是他是false啊,在if($delete)为假,不会执行removerFlash()啊,可是
为何第二次访问,值就没有了呢,那咱们还得从根源看起。
public function setFlash($key, $value = true, $removeAfterAccess = true)
{
    $counters = $this->get($this->flashParam, []);
    $counters[$key] = $removeAfterAccess ? -1 : 0;
    $_SESSION[$key] = $value;
    $_SESSION[$this->flashParam] = $counters;
}

    $counters首先执行get方法获取$this->flashParam的值(flashParam在上文有定义)至于为什么要获取他,咱们
下文再说

public $flashParam = '__flash';

    很明显,$removeAfterAccess默认值为真,所以$counters[$key]的值就为-1,然后将value存入session,
然后将"__flash"存入session,其值为-1,即$counters的值。
    然后我们再执行getFlash()方法的时候



public function getFlash($key, $defaultValue = null, $delete = false)
{
    $counters = $this->get($this->flashParam, []);//从session中获取$counters的值
    if (isset($counters[$key])) {//是否存在
        $value = $this->get($key, $defaultValue);//去除session中对应的值
        if ($delete) {
            $this->removeFlash($key);
        } elseif ($counters[$key] < 0) {
            // mark for deletion in the next request
            $counters[$key] = 1;
            $_SESSION[$this->flashParam] = $counters;
        }

        return $value;
    } else {
        return $defaultValue;
    }
}

    发现,还是没有执行removeFlash($key),然后思考,这个$counters[$key]是干啥的呢,为什么一直贯穿,为什么
,小于0的时候要改1呢,在我们使用setFlash()方法的时候,记得,他的值被赋值成了-1,于是我们点开$this->get()方法。
public function get($key, $defaultValue = null)
{
    $this->open();
    return isset($_SESSION[$key]) ? $_SESSION[$key] : $defaultValue;
}

发现其执行了一个open方法。
public function open()
{
    if ($this->getIsActive()) {
        return;
    }

    $this->registerSessionHandler();

    $this->setCookieParamsInternal();

    @session_start();

    if ($this->getIsActive()) {
        Yii::info('Session started', __METHOD__);
        $this->updateFlashCounters();//更新flash计数
    } else {
        $error = error_get_last();
        $message = isset($error['message']) ? $error['message'] : 'Failed to start session.';
        Yii::error($message, __METHOD__);
    }
}

open方法中,有一个updateFlashCounters(),找到其源码
protected function updateFlashCounters()
{
    $counters = $this->get($this->flashParam, []);
    if (is_array($counters)) {//如果$counters是一个数组
        foreach ($counters as $key => $count) {
            if ($count > 0) {//经行过getFlash()以后,其值变成了1
                unset($counters[$key], $_SESSION[$key]);
            } elseif ($count == 0) {
                $counters[$key]++;
            }
        }
        $_SESSION[$this->flashParam] = $counters;
    } else {
        // fix the unexpected problem that flashParam doesn't return an array
        unset($_SESSION[$this->flashParam]);
    }
}

哎,我们发现,在if($count>0)中,删除了$counters[$kye]和$_SESSION[$key]的值
于是恍然大悟,在第二次getFlash()的之后,由于没有了$counters[$key],所以直接返回了$defaultValue的值,默认为空。
public function getFlash($key, $defaultValue = null, $delete = false)
{
    $counters = $this->get($this->flashParam, []);//从session中获取$counters的值
    if (isset($counters[$key])) {//是否存在
        $value = $this->get($key, $defaultValue);//去除session中对应的值
        if ($delete) {
            $this->removeFlash($key);
        } elseif ($counters[$key] < 0) {
            // mark for deletion in the next request
            $counters[$key] = 1;
            $_SESSION[$this->flashParam] = $counters;
        }

        return $value;
    } else {
        return $defaultValue;
    }
}




  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值