在實際的項目開發過程中,用到了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原理后,相信大家都知道答案了吧!
