yii::$app->request和yii::$app->response是独立只读/输出对象,无自动同步;修改request不影响response,反之亦然;重定向须用url::to()并显式调用send()。

Yii 中 Yii::$app->request 和 Yii::$app->response 是独立对象,不自动同步状态
很多人以为改了 request 就会影响 response,或者反过来——其实完全不会。它们只是在同一个请求生命周期里被框架初始化的两个独立服务实例,没有引用或联动关系。
常见错误现象:$_GET 被手动修改后,期望 response 自动带上新参数重定向;或调用 $response->redirect() 后,误以为 request 会刷新为跳转后的 URL(并不会)。
-
request只读反映当前 HTTP 请求原始数据(GET/POST/headers/cookies),不可写 -
response是输出控制中心,负责设置状态码、header、body、重定向,但不读取也不改变request的任何字段 - 若需“基于请求生成响应”,必须显式调用,比如
$response->redirect(['site/index', 'id' => $request->get('id')])
重定向时别直接拼接 request 参数,用 Url::to() 更安全
手写 Location: /user/view?id=123 看似简单,但容易漏掉 URL 编码、路由规则适配、子目录部署路径前缀等问题。
使用场景:用户提交表单后跳回原列表页,或带筛选条件跳转。
- 错误写法:
$response->headers->set('Location', '/post/index?tag=' . $_GET['tag']);——$_GET['tag']可能含空格或特殊字符,未编码,且硬编码路径不兼容 URL 美化 - 正确做法:
$response->redirect(\yii\helpers\Url::to(['post/index', 'tag' => $request->get('tag')])); -
Url::to()自动处理路由匹配、URL 编码、baseUrl前缀(如部署在/myapp/下)
response 的 send() 必须在 exit 前调用,否则可能丢响应头
Yii 不会在你调用 redirect() 或 setStatusCode() 后自动发送 HTTP 头。它只把指令缓存在对象里,真正发出去靠 send()。
常见错误现象:页面空白、重定向失效、状态码仍是 200、自定义 header 没生效。
- 控制器中写
$response->redirect(...); return;→ 头没发,PHP 继续执行后续逻辑,最终输出默认 200 响应 - 正确做法:
return $response->redirect(...)->send();或$response->redirect(...)->send(); exit; - 注意:
send()只能调用一次;重复调用会触发 PHP warning 并中断输出
中间件或行为里操作 request/response 要小心生命周期顺序
Yii 的请求流程是:入口脚本 → 应用启动 → request 解析 → 路由匹配 → 控制器动作执行 → response 发送。中间件(如 BeforeAction 行为)插在动作执行前后,但无法干预 request 初始化前或 response->send() 之后的阶段。
性能与兼容性影响:在 beforeAction 里反复调用 $request->get() 没问题(内部已缓存),但若在 afterAction 里调用 $response->send(),可能已被主流程发过一次,导致 headers already sent 错误。
- 想统一加 header?用
on beforeRequest事件,或在Application::init()后立即设置$response->headers->set() - 想拦截并修改请求参数?只能在
beforeAction中通过Yii::$app->params或临时变量传递,不能改$request本身(它是只读的) - 调试时可用
var_dump($request->getUrl(), $response->getStatusCode());,但别放在send()之后











