ASP/ASP.NET 開發者習慣使用 Response 對象統一管理 HTTP 響應。本類在 PHP 中復刻核心功能:Header 管理、輸出緩衝、重定向、Gzip 壓縮,提供熟悉的開發體驗。
final class Response {
private $headers = [];
private $output = '';
private $compressLevel = 0;
public function addHeader($key, $value) {
$this->headers[$key] = $value;
return $this;
}
public function removeHeader($key) {
unset($this->headers[$key]);
return $this;
}
public function redirect($url) {
header('Location: ' . $url);
exit;
}
public function setOutput($output, $compressLevel = 0) {
$this->output = $output;
$this->compressLevel = (int)$compressLevel;
return $this;
}
private function compress($data, $level) {
if (headers_sent()) return $data;
if (connection_status() !== 0) return $data;
if (!extension_loaded('zlib') || ini_get('zlib.output_compression')) return $data;
$encoding = false;
if (!empty($_SERVER['HTTP_ACCEPT_ENCODING'])) {
if (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false) $encoding = 'gzip';
elseif (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'x-gzip') !== false) $encoding = 'x-gzip';
}
if (!$encoding) return $data;
$this->addHeader('Content-Encoding', $encoding);
return gzencode($data, $level);
}
public function output() {
$out = $this->compressLevel ? $this->compress($this->output, $this->compressLevel) : $this->output;
if (!headers_sent()) {
foreach ($this->headers as $k => $v) {
header("$k: $v");
}
}
echo $out;
}
// 便捷靜態方法
public static function json($data, $code = 200) {
$resp = new self();
$resp->addHeader('Content-Type', 'application/json; charset=utf-8')
->setOutput(json_encode($data, JSON_UNESCAPED_UNICODE))
->output();
http_response_code($code);
exit;
}
public static function xml($xmlString, $code = 200) {
$resp = new self();
$resp->addHeader('Content-Type', 'application/xml; charset=utf-8')
->setOutput($xmlString)
->output();
http_response_code($code);
exit;
}
}
$resp = new Response();
$resp->addHeader('X-Powered-By', 'MyFramework')
->setOutput('Hello World
', 6) // 級別 6 壓縮
->output();
try {
$user = User::find($id);
Response::json(['code' => 0, 'data' => $user]);
} catch (Exception $e) {
Response::json(['code' => 500, 'msg' => $e->getMessage()], 500);
}
$resp = new Response();
$resp->addHeader('Content-Type', 'application/octet-stream')
->addHeader('Content-Disposition', 'attachment; filename="export.csv"')
->addHeader('Content-Transfer-Encoding', 'binary')
->setOutput($csvData)
->output();
| 功能 | ASP Response | 本類實現 |
|---|---|---|
| Write/WriteLine | 直接輸出 | 緩衝至 setOutput() 最後統一 output() |
| Redirect | Response.Redirect | redirect() 同樣 exit |
| Buffer | Response.Buffer = True | 默認啟用(內部緩衝) |
| Gzip | IIS 級別配置 | 運行時動態判斷 Accept-Encoding |
| Expires/CacheControl | 屬性設置 | 通過 addHeader() 手動設置 |
echo、空白輸出、header() 都會導致 headers_sent() 為真,壓縮與 Header 設置失效。Response::instance() 獲取。zlib.output_compression 衝突:類中已檢測並跳過雙重壓縮。setOutput 載入整個文件到內存,應改用 readfile() 或流式輸出。