• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • http_response_code()

    (PHP 5 >= 5.4.0, PHP 7)

    获取/设置响应的 HTTP 状态码

    说明

    http_response_code([int $response_code]): mixed

    获取或者设置响应的 HTTP 状态码。

    参数

    $response_code

    可选的$response_code会设置响应的状态码。

    返回值

    如果提供了$response_code,将返回先前的状态码。如果未提供$response_code,会返回当前的状态码。在 Web 服务器环境里,这些状态码的默认值都是200

    如果在非 Web 服务器环境里调用(比如 CLI 应用里),不提供$response_code就会返回FALSE。在非 Web 服务器环境里,提供$response_code会返回TRUE(仅仅在先前没有设置过状态码的时候)。

    范例

    Web 服务器环境内使用http_response_code()

    <?php
    // 获取当前状态码,并设置新的状态码
    var_dump(http_response_code(404));
    //获取新的状态码
    var_dump(http_response_code());
    ?>
    

    以上例程会输出:

    int(200)
    int(404)
    

    在 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)
    

    参见

    If your version of PHP does not include this function:
    <?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;
        }
      }
    ?>
    In this example I am using $GLOBALS, but you can use whatever storage mechanism you like... I don't think there is a way to return the current status code:
    https://bugs.php.net/bug.php?id=52555
    For reference the error codes I got from PHP's source code:
    http://lxr.php.net/opengrok/xref/PHP_5_4/sapi/cgi/cgi_main.c#354
    And how the current http header is sent, with the variables it uses:
    http://lxr.php.net/opengrok/xref/PHP_5_4/main/SAPI.c#856
    Note that you can NOT set arbitrary response codes with this function, only those that are known to PHP (or the SAPI PHP is running on). 
    The following codes currently work as expected (with PHP running as Apache module):
    200 – 208, 226
    300 – 305, 307, 308
    400 – 417, 422 – 424, 426, 428 – 429, 431
    500 – 508, 510 – 511
    Codes 0, 100, 101, and 102 will be sent as "200 OK".
    Everything else will result in "500 Internal Server Error".
    If you want to send responses with a freestyle status line, you need to use the `header()` function:
    <?php header("HTTP/1.0 418 I'm A Teapot"); ?>
    
    You can also create a enum by extending the SplEnum class.
    <?php
    /** HTTP status codes */
    class HttpStatusCode extends SplEnum {
      const __default = self::OK;
      
      const SWITCHING_PROTOCOLS = 101;
      const OK = 200;
      const CREATED = 201;
      const ACCEPTED = 202;
      const NONAUTHORITATIVE_INFORMATION = 203;
      const NO_CONTENT = 204;
      const RESET_CONTENT = 205;
      const PARTIAL_CONTENT = 206;
      const MULTIPLE_CHOICES = 300;
      const MOVED_PERMANENTLY = 301;
      const MOVED_TEMPORARILY = 302;
      const SEE_OTHER = 303;
      const NOT_MODIFIED = 304;
      const USE_PROXY = 305;
      const BAD_REQUEST = 400;
      const UNAUTHORIZED = 401;
      const PAYMENT_REQUIRED = 402;
      const FORBIDDEN = 403;
      const NOT_FOUND = 404;
      const METHOD_NOT_ALLOWED = 405;
      const NOT_ACCEPTABLE = 406;
      const PROXY_AUTHENTICATION_REQUIRED = 407;
      const REQUEST_TIMEOUT = 408;
      const CONFLICT = 408;
      const GONE = 410;
      const LENGTH_REQUIRED = 411;
      const PRECONDITION_FAILED = 412;
      const REQUEST_ENTITY_TOO_LARGE = 413;
      const REQUESTURI_TOO_LARGE = 414;
      const UNSUPPORTED_MEDIA_TYPE = 415;
      const REQUESTED_RANGE_NOT_SATISFIABLE = 416;
      const EXPECTATION_FAILED = 417;
      const IM_A_TEAPOT = 418;
      const INTERNAL_SERVER_ERROR = 500;
      const NOT_IMPLEMENTED = 501;
      const BAD_GATEWAY = 502;
      const SERVICE_UNAVAILABLE = 503;
      const GATEWAY_TIMEOUT = 504;
      const HTTP_VERSION_NOT_SUPPORTED = 505;
    }
    On PHP 5.3 version, If you want to set HTTP response code. You can try this type of below trick :)
    <?php
    header('Temporary-Header: True', true, 404);
    header_remove('Temporary-Header');
    ?>
    
    Status codes as an array:
    <?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");
    ?>
    Source: Wikipedia "List_of_HTTP_status_codes"
    The note above from "Anonymous" is wrong. I'm running this behind the AWS Elastic Loadbalancer and trying the header(':'.$error_code...) method mentioned above is treated as invalid HTTP.
    The documentation for the header() function has the right way to implement this if you're still on < php 5.4:
    <?php
    header("HTTP/1.0 404 Not Found");
    ?>
    
    At least on my side with php-fpm and nginx this method does not change the text in the response, only the code.
    <?php
    // HTTP/1.1 404 Not Found
    http_response_code(404);
    ?>
    The resulting response is HTTP/1.1 404 OK
    http_response_code() does not actually send HTTP headers, it only prepares the header list to be sent later on.
    So you can call http_reponse_code() to set, get and reset the HTTP response code before it gets sent.
    Test code:
    <php
    http_response_code(500); // set the code
    var_dump(headers_sent()); // check if headers are sent
    http_response_code(200); // avoid a default browser page
    It's not mentioned explicitly, but the return value when SETTING, is the OLD status code.
    e.g.
    <?php
    $a = http_response_code();
    $b = http_response_code(202);
    $c = http_response_code();
    var_dump($a, $b, $c);
    // Result:
    // int(200)
    // int(200)
    // int(202)
    ?>
    
    http_response_code is basically a shorthand way of writing a http status header, with the added bonus that PHP will work out a suitable Reason Phrase to provide by matching your response code to one of the values in an enumeration it maintains within php-src/main/http_status_codes.h. Note that this means your response code must match a response code that PHP knows about. You can't create your own response codes using this method, however you can using the header method.
    In summary - The differences between "http_response_code" and "header" for setting response codes:
    1. Using http_response_code will cause PHP to match and apply a Reason Phrase from a list of Reason Phrases that are hard-coded into the PHP source code.
    2. Because of point 1 above, if you use http_response_code you must set a code that PHP knows about. You can't set your own custom code, however you can set a custom code (and Reason Phrase) if you use the header method.
    If you don't have PHP 5.4 and want to change the returned status code, you can simply write:
    <?php
    header(':', true, $statusCode);
    ?>
    The ':' are mandatory, or it won't work
    When setting the response code to non-standard ones like 420, Apache outputs 500 Internal Server Error.
    This happens when using header(0,0,420) and http_response_code(420).
    Use header('HTTP/1.1 420 Enhance Your Calm') instead.
    Note that the response code in the string IS interpreted and used in the access log and output via http_response_code().
    @craig at craigfrancis dot co dot uk@ wrote the function that replaces the original. It is very usefull, but has a bug. The original http_response_code always returns the previous or current code, not the code you are setting now. Here is my fixed version. I also use $GLOBALS to store the current code, but trigger_error() instead of exit. So now, how the function will behave in the case of error lies on the error handler. Or you can change it back to 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 = '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:
            trigger_error('Unknown http status code ' . $code, E_USER_ERROR); // exit('Unknown http status code "' . 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;
        // original function always returns the previous or current code
        return $prev_code;
      }
    }
    The limited list given by Stefan W is out of date. I have just tested 301 and 302 and both work.
    warning, it does not check if headers are already sent (if it is, it won't *actually* change the code, but a subsequent call will imply that it did!!),
    you might wanna do something like 
    function ehttp_response_code(int $response_code = NULL): int {
      if ($response_code === NULL) {
        return\ http_response_code();
      }
      if (\headers_sent()) {
        throw new\ Exception('tried to change http response code after sending headers!');
      }
      return\ http_response_code($response_code);
    }
    If you want to set a HTTP response code without the need of specifying a protocol version, you can actually do it without http_response_code():
    <?php
    header('Status: 404', TRUE, 404);
    ?>
    

    上篇:headers_sent()

    下篇:inet_ntop()