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

查看:17
本文介绍了如何使用 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.

推荐答案

控制器不应该回显数据!回显数据会导致各种问题,从测试环境无法识别数据,到无法发送header,甚至数据被截断.

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 动作通常使用 Controller::set() 来创建一个上下文,View 用它来渲染视图层.由于 CakePHP 使用的约定,您不需要手动创建和呈现视图.相反,一旦控制器操作完成,CakePHP 将处理渲染和交付视图.

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.

如果出于某种原因您想跳过默认行为,您可以从具有完全创建响应的操作中返回一个 CakeNetworkResponse 对象.

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

* 从 3.4 开始,这将是 CakeHttpResponse

食谱>控制器控制器操作

$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()不可用,直接写入body流即可,不会改变响应对象的状态:

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 发送正确的请求代码> 接受标题.

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天全站免登陆