Yii2.0 Cookies机制和使用方法

在实际的项目开发过程中,用到了Yii2.0 Cookies机制!但是遇到一个十分奇葩的问题,同一个YII框架,backend下Cookies能够正常存储于客户端,但是frontend始终不行。文章的最后将会解答这个疑问。

一、Yii2.0 Cookies的验证机制

Yii2.0的Cookies不同于常规的PHP的Cookie设置,YII2.0Cookies使用Cookie类自定义名称、值、过期时间;然后将设置好的cookie配置项装载到CookieCollection中。然后服务器端处理完客户端提交的数据后返回触发Yii::$app->response中的事件;将调用Yii::$app->response->send()方法。以下是send()方法的具体内容:

    public function send()
    {
        if ($this->isSent) {
            return;
        }
        $this->trigger(self::EVENT_BEFORE_SEND);
        $this->prepare();
        $this->trigger(self::EVENT_AFTER_PREPARE);
        $this->sendHeaders();
        $this->sendContent();
        $this->trigger(self::EVENT_AFTER_SEND);
        $this->isSent = true;
    }

其中,$this->sendHeaders()方法中包含对Cookies真正设置的操作,其方法内容如下:

    /**
     * Sends the response headers to the client
     */
    protected function sendHeaders()
    {
        if (headers_sent()) {
            return;
        }
        $statusCode = $this->getStatusCode();
        header("HTTP/{$this->version} $statusCode {$this->statusText}");
        if ($this->_headers) {
            $headers = $this->getHeaders();
            foreach ($headers as $name => $values) {
                $name = str_replace(' ', '-', ucwords(str_replace('-', ' ', $name)));
                // set replace for first occurrence of header but false afterwards to allow multiple
                $replace = true;
                foreach ($values as $value) {
                    header("$name: $value", $replace);
                    $replace = false;
                }
            }
        }
        $this->sendCookies();
    }

其中调用的$this->sendCookies()方法内容如下:

    /**
     * Sends the cookies to the client.
     */
    protected function sendCookies()
    {
        if ($this->_cookies === null) {
            return;
        }
        $request = Yii::$app->getRequest();
        if ($request->enableCookieValidation) {
            if ($request->cookieValidationKey == '') {
                throw new InvalidConfigException(get_class($request) . '::cookieValidationKey must be configured with a secret key.');
            }
            $validationKey = $request->cookieValidationKey;
        }
        foreach ($this->getCookies() as $cookie) {
            $value = $cookie->value;
            if ($cookie->expire != 1  && isset($validationKey)) {
                $value = Yii::$app->getSecurity()->hashData(serialize($value), $validationKey);
            }
            setcookie($cookie->name, $value, $cookie->expire, $cookie->path, $cookie->domain, $cookie->secure, $cookie->httpOnly);
        }
        $this->getCookies()->removeAll();
    }

到这里,相信大家对Yii2.0 Cookies机制有一个全新的认识了吧!

二、Yii2.0 Cookies的具体使用方法

 1、main.php或main-local.php配置文件中添加以下代码:

        'request' => [
            // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
            'cookieValidationKey' => 'fcuVvgFv0Vex88Qm5N2-h6HH5anM4HEd',
        ],

2、使用Yii2.0 Cookie类配置具体的Cookie参数:

 1        $rname0 = new Cookie([
 2                       'name' => 'rname_b',
 3                       'value' => '1111111',
 4                       'expire' => time() + 14400 // 设置过期时间(一个月)
 5                   ]);
 6        $ruser0 = new Cookie([
 7                       'name' => 'ruser_b',
 8                       'value' => '2222222',
 9                       'expire' => time() + 14400 // 设置过期时间(一个月)
10                   ]);

3、调用Yii::$app->response->cookies实例将配置好的cookies项装载到CookieColletion中:

$resCookies = Yii::$app->response->cookies;

$resCookies->add($rname0);
$resCookies->add($ruser0);

至此,Cookies相关配置操作已经完成,服务端处理完数据将内容发送到客户端将会触发Yii::$app->response中的事件,就会自动将Cookies写进客户端了!是不是很方便呀!

回到最初的疑问,为什么会出现那么奇葩的现象尼??主要看以下代码有啥区别:

// 【代码一】cookies正常写入的代码
echo json_encode($response, JSON_UNESCAPED_UNICODE);

// 【代码二】cookies无法正常写入的代码
echo json_encode($response, JSON_UNESCAPED_UNICODE);
exit;

就因为代码中多了一个exit导致Cookie无法写入客户端。大家了解了YII2.0 Cookies原理后,相信大家都知道答案了吧!

原文地址:https://www.cnblogs.com/itsharehome/p/5010732.html