在Yii中使用了第三方模板引擎或访问第三方api的url时,输出模板的时候触发了Yii Response类的异常。bug如下:
An Error occurred while handling another error:
yii\web\HeadersAlreadySentException: Headers already sent in \vendor\topthink\think-template\src\Template.php on line 194. in \vendor\yiisoft\yii2\web\Response.php:366
Stack trace:
#0 \vendor\yiisoft\yii2\web\Response.php(339): yii\web\Response->sendHeaders()
#1 \vendor\yiisoft\yii2\web\ErrorHandler.php(135): yii\web\Response->send()
#2 \vendor\yiisoft\yii2\base\ErrorHandler.php(111): yii\web\ErrorHandler->renderException(Object(yii\web\HeadersAlreadySentException))
#3 [internal function]: yii\base\ErrorHandler->handleException(Object(yii\web\HeadersAlreadySentException))
#4 {main}
Previous exception:
yii\web\HeadersAlreadySentException: Headers already sent in \vendor\topthink\think-template\src\Template.php on line 194. in \vendor\yiisoft\yii2\web\Response.php:366
Stack trace:
#0 \vendor\yiisoft\yii2\web\Response.php(339): yii\web\Response->sendHeaders()
#1 \vendor\yiisoft\yii2\base\Application.php(392): yii\web\Response->send()
#2 \backend\web\index.php(17): yii\base\Application->run()
#3 {main}
随之百度一下,说是在操作echo/var_dump/print_r之后在结尾die或者exit可以解决...唔,测试了一下确实可以,但是!这么丑的解决办法肯定不是最好的方案。如果直接die或者exit的话以后可能会导致各种猎奇问题产生(如:debug记录缺失、cli异常结束、回调方法失效等),那就看一下源码吧。
/**
* Sends the response headers to the client.
*/
protected function sendHeaders()
{
if (headers_sent($file, $line)) {
throw new HeadersAlreadySentException($file, $line);
}
if ($this->_headers) {
foreach ($this->getHeaders() 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;
}
}
}
$statusCode = $this->getStatusCode();
header("HTTP/{$this->version} {$statusCode} {$this->statusText}");
$this->sendCookies();
}
在yii/web/Response里sendHeaders方法执行前进行了headers_sent()的验证,所以导致了异常的产生。解决方法就是在模板输出前先把headers设置好,所以在基类控制器重写了模板输出的fetch()方法,并在执行前先使用Response->send()设置headers。代码如下:
/**
* 重写模板渲染
* @access public
* @param string $template 模板文件
* @param array $vars 模板变量
* @param array $config 模板参数
* @return void
*/
protected function fetch($template, $vars = [], $config = []) : void
{
Yii::$app->response->send();
$this->view->fetch($template,$vars,$config);
}
访问API的curl时如下:
public function actionGetip($ip)
{
if($ip !=''){
Yii::$app->response->send();
$url = 'http://xxx.com/json/'.$ip.'?lang=zh-CN';
SiteController::curl_get_contents($url);
}
else{
$ips['ip'] = yii::$app->getRequest()->getUserIP();
return $ips;
}
}
参考网址:
https://www.yiichina.com/question/3833
https://blog.csdn.net/qq_22845065/article/details/102976690
原文地址:网络
转载请注明: ITTXX.CN--分享互联网 » yii\web\HeadersAlreadySentException解决方法
最后更新:2021-07-05 19:06:15