Response 响应类
startmvc\core\Response 是站点的唯一响应出口:状态码、响应头、Cookie、响应体(含文件下载)以及调试追踪面板,全部由它统一发送。控制器既可以 return 一个 Response 对象,也可以直接调用它的方法链。
快速开始
use startmvc\core\Response;
return (new Response())->json(['ok' => true]); // JSON
return (new Response())->text('hello'); // 纯文本
return (new Response())->html('<h1>Hi</h1>'); // HTML
return (new Response())->redirect('/login'); // 302 重定向
return (new Response())->noContent(); // 204 无内容
return (new Response())->download('/data/a.zip'); // 文件下载
除 send() 外,所有设置类方法都返回 $this,因此可以任意链式组合。
return (new Response())
->setStatusCode(201)
->setHeader('X-Trace-Id', 'abc123')
->cookie('visited', '1', ['expire' => 86400])
->json(['created' => true]);
响应类型
json($data, $status = 200)—— JSON 响应,响应头application/json; charset=utf-8,采用JSON_UNESCAPED_UNICODE编码,中文不转义。html($content, $status = 200)—— HTML 响应,响应头text/html; charset=utf-8。text($content, $status = 200)—— 纯文本响应,响应头text/plain; charset=utf-8。noContent($status = 204)—— 无响应体的响应,默认 204。setContent($content)—— 直接设置响应体,不改变 Content-Type。
JSON 响应由 json_encode 生成,斜杠会被转义,这是 PHP 的默认行为,属正常输出:
return (new Response())->json(['name' => '张三', 'url' => url('home/index/index')]);
// 输出:{"name":"张三","url":"\/home\/index\/index"}
状态码与响应头
setStatusCode($code)—— 设置状态码。setHeader($key, $value)—— 设置单个响应头。setHeaders(array $headers)—— 批量设置响应头,键为头名、值为头值。getStatusCode()—— 读取状态码。getHeader($key)—— 读取指定响应头,键名大小写不敏感,不存在时返回null。getHeaders()—— 读取全部响应头。getContent()—— 读取响应体。getContentType()—— 读取 Content-Type 的媒体类型部分(不含 charset 等参数,统一小写);未设置时返回空串。isSent()—— 本次响应是否已经发送。
重定向
redirect($url, $status = 302) 设置 Location 响应头。$status 可用 301(永久)/ 302(临时)/ 303 / 307 / 308。
return (new Response())->redirect('/new-url', 301);
重定向只负责设置响应,不会终止当前方法。需要在设置后立即停止后续逻辑,请自行 return;控制器里的 $this->redirect() 则通过抛出 HttpResponseException 立即中断,详见「重定向与跳转」一节。
文件下载
download($file, $name = null, $mime = null):
$file—— 文件真实路径,响应体在发送时以流式读取,不会把大文件读进内存。$name—— 下载时展示的文件名,默认取basename($file);同时给出 ASCII 回退名与 RFC 5987 的 UTF-8 文件名,中文名在各浏览器下均可正常显示。$mime—— MIME 类型,默认application/octet-stream。
文件不存在或不可读时抛出 RuntimeException(属于调用方错误,快速失败)。
return (new Response())->download(
ROOT_PATH . 'runtime/export/orders.xlsx',
'订单导出.xlsx',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
);
Cookie
cookie($key, $value, array $options = []) 收集一个待发送的 Cookie。真正的 setcookie 在 send() 时统一交给 Cookie::set() 完成,因此键名前缀(cookie_prefix)与安全默认值(secure 自动检测、SameSite、HttpOnly)与框架其它地方完全一致。
return (new Response())->html($html)->cookie('visited', '1', ['expire' => 86400]);
$options 支持 expire / path / domain / secure / httponly / samesite,含义同 Cookie::set()。
发送响应与调试追踪面板
send() 负责把状态码、响应头、Cookie 与响应体真正发送出去,并附加调试追踪面板。它由框架在请求结束时自动调用,通常不需要手动调用;send() 是幂等的,重复调用只发送一次。
调试追踪面板(trace)的附加规则:
- 只对 HTML 类页面附加(未声明 Content-Type 时视为 HTML)。
- JSON、纯文本、文件下载,以及无响应体的 204 / 304 / 3xx 响应一律不附加 —— 往这些响应体里塞 HTML 会直接破坏客户端解析。
- 受
config/common.php的trace开关控制,生产环境请关闭。 - 可用
withTrace(false)/withTrace(true)显式覆盖自动判定;但无响应体响应与文件下载始终不附加,显式开关也无法覆盖。
完整示例:一个 JSON 接口
use startmvc\core\Controller;
use startmvc\core\Response;
class ApiController extends Controller
{
public function userAction(int $id = 0)
{
$user = $this->getUserById($id); // 由业务方法取得数据
if (empty($user)) {
return (new Response())->json(['code' => 0, 'msg' => '用户不存在'], 404);
}
return (new Response())->json(['code' => 1, 'data' => $user]);
}
}
与控制器便捷方法的关系
控制器另提供一组便捷方法,内部同样走 Response,可直接在控制器方法里调用:
$this->json($data)—— 输出 JSON 并立即中断执行。$this->redirect($url)—— 跳转,同样立即中断执行($url为空时跳转到/)。$this->response($code, $msg, $url, $data, $ajax)—— 统一响应入口:Ajax 请求返回 JSON,普通请求渲染跳转页。$this->success($msg, $url, $data, $ajax)/$this->error(...)—— 成功 / 失败的提示与跳转,是response()的语法糖(code分别为 1 与 0)。$this->content($content)—— 以text/plain直接输出内容,不终止后续代码。$this->notFound()—— 只设置 404 状态码并发送响应头,既不输出响应体也不终止执行;要终止并渲染 404 页面,请抛出\Exception('页面不存在', 404)。
需要更细的控制(自定义响应头、Cookie、下载文件名等)时,直接 return 一个 Response 对象即可;返回值的各种形态与优先级见「控制器数据输出」一节。