如何在CakePHP 3.4中输出自定义的HTTP正文内容?回显会导致“无法发出标题”的错误。

7

使用CakePHP 3.4和PHP 7.0。

我试图编写一个非常简单的控制器方法以输出一些JSON。但是它输出了“无法修改头文件...”。

public function test() {
    $this->autoRender = false;
    echo json_encode(['method' => __METHOD__, 'class' => get_called_class()]);
}

浏览器输出
{"method":"App\\Controller\\SomeController::test", "class":"App\\Controller\\SomeController"}

Warning (512): Unable to emit headers. Headers sent in file=...
Warning (2): Cannot modify header information - headers already sent by (output started at ...)
Warning (2): Cannot modify header information - headers already sent by (output started at ...)

我完全理解为什么PHP会抱怨这个。问题是为什么CakePHP也会抱怨,我能做些什么呢?

需要注意的是,CakePHP 2.x允许这样做。

2个回答

14

控制器绝不应该回显数据!回显数据可能导致各种问题,从在测试环境中无法识别数据,到无法发送标头,甚至截断数据。

即使在CakePHP 2.x中这样做也是错误的,尽管在某些情况下它可能已经起作用,甚至在大多数情况下都是如此。随着新的HTTP堆栈的引入,CakePHP现在明确检查发送的标头,然后才回显响应,并相应地触发错误。

发送自定义输出的正确方式是配置并返回响应对象,或使用序列化视图,在3.x中仍然是相同的。

来自文档的引用:

控制器操作通常使用 Controller :: set()创建View用于呈现视图层的上下文。由于CakePHP使用的约定,您不需要手动创建和呈现视图。相反,一旦控制器操作完成,CakePHP将处理呈现和传递视图。

如果出于某种原因您想跳过默认行为,则可以从操作中返回一个完全创建的响应Cake \ Network \ Response 对象。

* 自3.4起,那将是 \ Cake \ Http \ Response

菜谱 > 控制器 > 控制器操作

配置响应

使用符合PSR-7的接口

$content = json_encode(['method' => __METHOD__, 'class' => get_called_class()]);

$this->response = $this->response->withStringBody($content);
$this->response = $this->response->withType('json');
// ...

return $this->response;

符合 PSR-7 标准的接口使用不可变方法,因此使用 withStringBody()withType() 的返回值。在 CakePHP < 3.4.3 中,withStringBody() 不可用,您可以直接写入正文流而不更改响应对象的状态:

$this->response->getBody()->write($content);

使用已弃用的接口

$content = json_encode(['method' => __METHOD__, 'class' => get_called_class()]);

$this->response->body($content);
$this->response->type('json');
// ...

return $this->response;

使用序列化视图

$content = ['method' => __METHOD__, 'class' => get_called_class()];

$this->set('content', $content);
$this->set('_serialize', 'content');

这需要同时使用请求处理组件,并启用扩展解析以及使用相应带有.json的URL,或发送具有application/json接受标头的适当请求。

另请参阅


0
CakePHP 3有一个叫做JSON views的东西,它允许你返回JSON数据。我以前没有做过任何CakePHP的项目,所以我不知道请求的生命周期,但值得研究一下。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接