如何使用CakePHP 3.4输出自定义HTTP正文内容?回声导致“无法发出报头".错误 [英] How to output custom HTTP body contents with CakePHP 3.4? Echoing causes "Unable to emit headers" error

查看:281
本文介绍了如何使用CakePHP 3.4输出自定义HTTP正文内容?回声导致“无法发出报头".错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用CakePHP 3.4,PHP 7.0.

Using CakePHP 3.4, PHP 7.0.

我正在尝试做一个非常简单的控制器方法来输出一些JSON.它正在输出无法修改标题...".

I'm attempting to do a really simple controller method to output some JSON. It is outputting "Cannot modify headers...".

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会抱怨,我该怎么办?

I fully understand why PHP complains about this. The question is why does CakePHP complain and what can I do about it?

应该注意的是CakePHP 2.x允许这样做.

It should be noted that CakePHP 2.x allowed this.

推荐答案

控制器永远不要回显数据!回响数据会导致各种问题,从测试环境中无法识别的数据到无法发送的报头,甚至是数据都被切断.

Controllers should never echo data! Echoing data can lead to all kinds of problems, from the data not being recognized in the test environment, to headers not being able to be sent, and even data being cut off.

以这种方式进行操作在CakePHP 2.x中已经是错误的,即使它在某些情况下(甚至在大多数情况下)都可行.通过引入新的HTTP堆栈,CakePHP现在在回显响应之前显式检查发送的标头,并相应地触发错误.

Doing it that way was already wrong in CakePHP 2.x, even though it might have worked in some, maybe even most situations. With the introduction of the new HTTP stack, CakePHP now explicitly checks for sent headers before echoing the response, and will trigger an error accordingly.

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

The proper way to send custom output was to configure and return the response object, or to use serialized views, and it's still the same in 3.x.

从文档中引用:

控制器动作通常使用Controller::set()来创建View用于渲染视图层的上下文.由于CakePHP使用的约定,因此无需手动创建和呈现视图.相反,一旦控制器动作完成,CakePHP将处理呈现和交付View.

Controller actions generally use Controller::set() to create a context that View uses to render the view layer. Because of the conventions that CakePHP uses, you don’t need to create and render the view manually. Instead, once a controller action has completed, CakePHP will handle rendering and delivering the View.

如果出于某种原因想要跳过默认行为,则可以从具有完整创建的响应的操作中返回Cake\Network\Response对象.

If for some reason you’d like to skip the default behavior, you can return a Cake\Network\Response object from the action with the fully created response.

*从3.4开始为\Cake\Http\Response

Cookbook>控制器>控制器操作

Cookbook > Controllers > Controller Actions

$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()不可用,您可以直接写入正文流,而不会更改响应对象的状态:

The PSR-7 compliant interface uses immutable methods, hence the utilization of the return value of withStringBody() and withType(). In CakePHP < 3.4.3, withStringBody() is not available, and you can instead directly write to the body stream, which will not change the state of the response object:

$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 accept标头的适当请求.

This requires to also use the request handler component, and to enable extensing parsing and using correponsing URLs with .json appended, or to send a proper request with a application/json accept header.

这篇关于如何使用CakePHP 3.4输出自定义HTTP正文内容?回声导致“无法发出报头".错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆