PHP Conference Japan 2024

http_response_code

(PHP 5 >= 5.4.0, PHP 7, PHP 8)

http_response_code取得或設定 HTTP 回應碼

說明

http_response_code(int $response_code = 0): int|bool

取得或設定 HTTP 回應狀態碼。

參數

response_code

選用的 response_code 將設定回應碼。

回傳值

如果提供了 response_code,則會回傳先前的狀態碼。如果未提供 response_code,則會回傳目前的狀態碼。如果在網路伺服器環境中使用,這兩個值預設都會是 200 狀態碼。

如果未提供 response_code 且未在網路伺服器環境(例如從 CLI 應用程式)中呼叫,則會傳回 false。如果提供了 response_code 且未在網路伺服器環境中呼叫(但僅限於先前未設定任何回應狀態時),則會傳回 true

範例

範例 #1 在網路伺服器環境中使用 http_response_code()

<?php

// 取得目前的回應碼並設定新的回應碼
var_dump(http_response_code(404));

// 取得新的回應碼
var_dump(http_response_code());
?>

以上範例將輸出

int(200)
int(404)

範例 #2 在 CLI 環境中使用 http_response_code()

<?php

// 取得目前的預設回應碼
var_dump(http_response_code());

// 設定回應碼
var_dump(http_response_code(201));

// 取得新的回應碼
var_dump(http_response_code());
?>

以上範例將輸出

bool(false)
bool(true)
int(201)

另請參閱

  • header() - 傳送原始 HTTP 標頭
  • headers_list() - 傳回已傳送(或準備傳送)的回應標頭清單

新增註解

使用者貢獻的註解 12 則註解

craig at craigfrancis dot co dot uk
12 年前
如果您的 PHP 版本不包含此函式

<?php

if (!function_exists('http_response_code')) {
function
http_response_code($code = NULL) {

if (
$code !== NULL) {

switch (
$code) {
case
100: $text = 'Continue'; break;
case
101: $text = 'Switching Protocols'; break;
case
200: $text = 'OK'; break;
case
201: $text = 'Created'; break;
case
202: $text = 'Accepted'; break;
case
203: $text = 'Non-Authoritative Information'; break;
case
204: $text = 'No Content'; break;
case
205: $text = 'Reset Content'; break;
case
206: $text = 'Partial Content'; break;
case
300: $text = 'Multiple Choices'; break;
case
301: $text = 'Moved Permanently'; break;
case
302: $text = 'Moved Temporarily'; break;
case
303: $text = 'See Other'; break;
case
304: $text = 'Not Modified'; break;
case
305: $text = 'Use Proxy'; break;
case
400: $text = 'Bad Request'; break;
case
401: $text = 'Unauthorized'; break;
case
402: $text = 'Payment Required'; break;
case
403: $text = 'Forbidden'; break;
case
404: $text = 'Not Found'; break;
case
405: $text = 'Method Not Allowed'; break;
case
406: $text = 'Not Acceptable'; break;
case
407: $text = 'Proxy Authentication Required'; break;
case
408: $text = 'Request Time-out'; break;
case
409: $text = 'Conflict'; break;
case
410: $text = 'Gone'; break;
case
411: $text = 'Length Required'; break;
case
412: $text = 'Precondition Failed'; break;
case
413: $text = 'Request Entity Too Large'; break;
case
414: $text = 'Request-URI Too Large'; break;
case
415: $text = 'Unsupported Media Type'; break;
case
500: $text = 'Internal Server Error'; break;
case
501: $text = 'Not Implemented'; break;
case
502: $text = 'Bad Gateway'; break;
case
503: $text = 'Service Unavailable'; break;
case
504: $text = 'Gateway Time-out'; break;
case
505: $text = 'HTTP Version not supported'; break;
default:
exit(
'Unknown http status code "' . htmlentities($code) . '"');
break;
}

$protocol = (isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0');

header($protocol . ' ' . $code . ' ' . $text);

$GLOBALS['http_response_code'] = $code;

} else {

$code = (isset($GLOBALS['http_response_code']) ? $GLOBALS['http_response_code'] : 200);

}

return
$code;

}
}

?>

在此範例中,我使用的是 $GLOBALS,但您可以使用任何您喜歡的儲存機制... 我認為沒有辦法傳回目前的狀態碼

https://bugs.php.net/bug.php?id=52555

作為參考,我從 PHP 的原始碼中取得的錯誤碼

http://lxr.php.net/opengrok/xref/PHP_5_4/sapi/cgi/cgi_main.c#354

以及目前 http 標頭的傳送方式,以及它使用的變數

http://lxr.php.net/opengrok/xref/PHP_5_4/main/SAPI.c#856
Stefan W
10 年前
請注意,您無法使用此函式設定任意回應碼,只能設定 PHP(或執行 PHP 的 SAPI)已知的回應碼。

以下程式碼目前在預期的情況下運作(使用 PHP 作為 Apache 模組)
200 – 208, 226
300 – 305, 307, 308
400 – 417, 422 – 424, 426, 428 – 429, 431
500 – 508, 510 – 511

代碼 0、100、101 和 102 將會以「200 OK」送出。

其他所有代碼都會導致「500 內部伺服器錯誤」。

如果您想要用自定義的狀態列發送回應,您需要使用 `header()` 函式

<?php header("HTTP/1.0 418 I'm A Teapot"); ?>
Thomas A. P.
9 年前
當設定回應碼為非標準的代碼,例如 420 時,Apache 會輸出 500 內部伺服器錯誤。

使用 header(0,0,420) 和 http_response_code(420) 時會發生這種情況。
請改用 header('HTTP/1.1 420 Enhance Your Calm')。

請注意,字串中的回應碼會被解讀並用於存取日誌,並透過 http_response_code() 輸出。
divinity76 at gmail dot com
4 年前
如果您需要 http_response_code() 不支援的回應碼,例如 WebDAV / RFC4918 的「HTTP 507 儲存空間不足」,請嘗試

<?php
header
($_SERVER['SERVER_PROTOCOL'] . ' 507 Insufficient Storage');
?>
結果:類似以下

HTTP/1.1 507 Insufficient Storage
匿名
11 年前
狀態碼陣列

<?php
$http_status_codes
= array(100 => "Continue", 101 => "Switching Protocols", 102 => "Processing", 200 => "OK", 201 => "Created", 202 => "Accepted", 203 => "Non-Authoritative Information", 204 => "No Content", 205 => "Reset Content", 206 => "Partial Content", 207 => "Multi-Status", 300 => "Multiple Choices", 301 => "Moved Permanently", 302 => "Found", 303 => "See Other", 304 => "Not Modified", 305 => "Use Proxy", 306 => "(Unused)", 307 => "Temporary Redirect", 308 => "Permanent Redirect", 400 => "Bad Request", 401 => "Unauthorized", 402 => "Payment Required", 403 => "Forbidden", 404 => "Not Found", 405 => "Method Not Allowed", 406 => "Not Acceptable", 407 => "Proxy Authentication Required", 408 => "Request Timeout", 409 => "Conflict", 410 => "Gone", 411 => "Length Required", 412 => "Precondition Failed", 413 => "Request Entity Too Large", 414 => "Request-URI Too Long", 415 => "Unsupported Media Type", 416 => "Requested Range Not Satisfiable", 417 => "Expectation Failed", 418 => "I'm a teapot", 419 => "Authentication Timeout", 420 => "Enhance Your Calm", 422 => "Unprocessable Entity", 423 => "Locked", 424 => "Failed Dependency", 424 => "Method Failure", 425 => "Unordered Collection", 426 => "Upgrade Required", 428 => "Precondition Required", 429 => "Too Many Requests", 431 => "Request Header Fields Too Large", 444 => "No Response", 449 => "Retry With", 450 => "Blocked by Windows Parental Controls", 451 => "Unavailable For Legal Reasons", 494 => "Request Header Too Large", 495 => "Cert Error", 496 => "No Cert", 497 => "HTTP to HTTPS", 499 => "Client Closed Request", 500 => "Internal Server Error", 501 => "Not Implemented", 502 => "Bad Gateway", 503 => "Service Unavailable", 504 => "Gateway Timeout", 505 => "HTTP Version Not Supported", 506 => "Variant Also Negotiates", 507 => "Insufficient Storage", 508 => "Loop Detected", 509 => "Bandwidth Limit Exceeded", 510 => "Not Extended", 511 => "Network Authentication Required", 598 => "Network read timeout error", 599 => "Network connect timeout error");
?>

資料來源:維基百科「List_of_HTTP_status_codes」
viaujoc at videotron dot ca
4 年前
不要混用 http_response_code() 和手動設定回應碼標頭,因為網路伺服器實際返回的 HTTP 狀態碼可能與預期不符。如果先前已使用 header() 函式設定了回應碼,則 http_response_code() 將無法運作。範例

<?php
header
('HTTP/1.1 401 Unauthorized');
http_response_code(403);
print(
http_response_code());
?>

原始 HTTP 回應將會是(請注意第一行上的實際狀態碼與主體中列印的 http_response_code 不符)

HTTP/1.1 401 Unauthorized
日期:週二,2020 年 11 月 24 日 13:49:08 GMT
伺服器:Apache
連線:升級,保持連線
保持連線:逾時=5,最大=100
傳輸編碼:分塊
內容類型:text/html; charset=UTF-8

403

我只在 Apache 上測試過。我不確定這種行為是 Apache 特有的還是所有 PHP 發行版共有的。
Rob Zazueta
11 年前
上面「匿名」的註記是錯誤的。我在 AWS Elastic Load Balancer 後面執行這個程式,嘗試上面提到的 header(':'.$error_code...) 方法會被視為無效的 HTTP。

如果您仍在使用 php 5.4 之前的版本,header() 函式的文件中記載了正確的實作方式

<?php
header
("HTTP/1.0 404 Not Found");
?>
匿名
12 年前
如果您沒有 PHP 5.4,並且想要更改返回的狀態碼,您可以簡單地寫入
<?php
header
(':', true, $statusCode);
?>

':' 是必需的,否則將無法運作
Steven
9 年前
http_response_code 基本上是一種簡寫 HTTP 狀態標頭的方式,它還有一個額外的好處:PHP 會根據您提供的回應碼,從 php-src/main/http_status_codes.h 這個檔案中維護的列舉值找出一個合適的「原因片語」(Reason Phrase)。請注意,這表示您的回應碼必須與 PHP 已知的回應碼相符。您無法使用這個方法建立自己的回應碼,但您可以使用 header 方法來達成。

總而言之 - 使用 "http_response_code" 和 "header" 設定回應碼的差異

1. 使用 http_response_code 會讓 PHP 從硬編碼在 PHP 原始碼中的「原因片語」列表中匹配並套用一個「原因片語」。

2. 由於上述第 1 點,如果您使用 http_response_code,則必須設定 PHP 已知的代碼。您無法設定自己的自定義代碼,但是如果您使用 header 方法,則可以設定自定義代碼(和「原因片語」)。
Richard F.
11 年前
至少在我這邊使用 php-fpm 和 nginx 的情況下,這個方法只會更改回應中的代碼,而不會更改回應的文字內容。

<?php

// HTTP/1.1 404 Not Found
http_response_code(404);

?>

產生的回應是 HTTP/1.1 404 OK
stephen at bobs-bits dot com
10 年前
文件中沒有明確提到,但在「設定」回應碼時,回傳值是「舊的」狀態碼。
例如:
<?php

$a
= http_response_code();
$b = http_response_code(202);
$c = http_response_code();

var_dump($a, $b, $c);

// 結果:
// int(200)
// int(200)
// int(202)
?>
yefremov {dot} sasha () gmail {dot} com
9 年前
@craig at craigfrancis dot co dot uk@ 撰寫了取代原始函式的函式。它非常有用,但有一個錯誤。原始的 http_response_code 總是返回先前的或目前的代碼,而不是您現在設定的代碼。這是我的修正版本。我也使用 $GLOBALS 來儲存目前的代碼,但使用 trigger_error() 而不是 exit。所以現在,函式在發生錯誤時的行為取決於錯誤處理程式。或者您可以將其改回 exit()。

if (!function_exists('http_response_code')) {
function http_response_code($code = NULL) {
$prev_code = (isset($GLOBALS['http_response_code']) ? $GLOBALS['http_response_code'] : 200);

if ($code === NULL) {
return $prev_code;
}

switch ($code) {
case 100: $text = 'Continue'; break;
case 101: $text = 'Switching Protocols'; break;
case 200: $text = 'OK'; break;
case 201: $text = 'Created'; break;
case 202: $text = 'Accepted'; break;
case 203: $text = 'Non-Authoritative Information'; break;
case 204: $text = 'No Content'; break;
case 205: $text = 'Reset Content'; break;
case 206: $text = 'Partial Content'; break;
case 300: $text = 'Multiple Choices'; break;
case 301: $text = 'Moved Permanently'; break;
case 302: $text = 'Moved Temporarily'; break;
case 303: $text = 'See Other'; break;
case 304: $text = 'Not Modified'; break;
case 305: $text = 'Use Proxy'; break;
case 400: $text = '錯誤的要求'; break;
case 401: $text = '未經授權'; break;
case 402: $text = '需要付款'; break;
case 403: $text = '禁止'; break;
case 404: $text = '找不到'; break;
case 405: $text = '不允許的方法'; break;
case 406: $text = '不可接受'; break;
case 407: $text = '需要代理伺服器驗證'; break;
case 408: $text = '要求逾時'; break;
case 409: $text = '衝突'; break;
case 410: $text = '已消失'; break;
case 411: $text = '需要長度'; break;
case 412: $text = '前提條件失敗'; break;
case 413: $text = '請求實體過大'; break;
case 414: $text = '請求 URI 過長'; break;
case 415: $text = '不支援的媒體類型'; break;
case 500: $text = '內部伺服器錯誤'; break;
case 501: $text = '未實作'; break;
case 502: $text = '閘道器錯誤'; break;
case 503: $text = '服務無法使用'; break;
case 504: $text = '閘道器逾時'; break;
case 505: $text = '不支援的 HTTP 版本'; break;
default
trigger_error('未知的 http 狀態碼 ' . $code, E_USER_ERROR); // exit('未知的 http 狀態碼 "' . htmlentities($code) . '"');
return $prev_code;
}

$protocol = (isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0');
header($protocol . ' ' . $code . ' ' . $text);
$GLOBALS['http_response_code'] = $code;

// 原函式一律傳回先前的或目前的程式碼
return $prev_code;
}
}
To Top