PHP http_response_code() 函数

http_response_code() 函数用于获取或设置 HTTP 响应状态码。

HTTP 状态码是服务器对客户端请求的响应状态的三位数字代码。该函数提供了一种简单的方式来设置或检索当前的 HTTP 响应状态码。

提示:该函数在 PHP 5.4.0 及更高版本中可用。在早期版本中,需要使用 header() 函数来设置状态码。

语法

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

参数

参数 类型 描述
$response_code int 可选的。要设置的 HTTP 响应状态码。
  • 如果提供了此参数,函数将设置状态码并返回之前的状态码(或 true
  • 如果省略此参数,函数将返回当前的状态码

返回值

返回值 描述
int 当不传递参数时:返回当前的 HTTP 响应状态码。
当传递参数时:返回之前的状态码。
true 当传递参数且成功设置状态码,但之前没有状态码时返回 true
false 如果传递了无效的状态码,或者头信息已经发送导致无法设置状态码时返回 false

常见 HTTP 状态码

状态码 类别 描述
200 成功 OK - 请求成功
301 重定向 Moved Permanently - 永久重定向
302 重定向 Found - 临时重定向
304 重定向 Not Modified - 资源未修改
400 客户端错误 Bad Request - 请求无效
401 客户端错误 Unauthorized - 需要认证
403 客户端错误 Forbidden - 禁止访问
404 客户端错误 Not Found - 资源未找到
405 客户端错误 Method Not Allowed - 方法不允许
500 服务器错误 Internal Server Error - 服务器内部错误
502 服务器错误 Bad Gateway - 错误的网关
503 服务器错误 Service Unavailable - 服务不可用

示例

示例 1:基本使用 - 获取和设置状态码

以下示例展示了如何获取和设置 HTTP 响应状态码。

<?php
// 获取当前状态码(默认是200)
$current_code = http_response_code();
echo "当前HTTP状态码: " . $current_code . "\n";

// 设置404状态码
$previous_code = http_response_code(404);
echo "之前的状态码: " . $previous_code . "\n";
echo "新的状态码: " . http_response_code() . "\n";

// 设置500状态码
http_response_code(500);
echo "当前状态码: " . http_response_code() . "\n";

// 重置为200
http_response_code(200);
?>

示例 2:处理错误页面

根据不同的错误设置相应的 HTTP 状态码。

<?php
// 假设根据某些条件显示错误页面
$error_type = 'not_found'; // 可以是 'not_found', 'forbidden', 'server_error' 等

switch ($error_type) {
    case 'not_found':
        http_response_code(404);
        $error_message = "页面未找到";
        break;
    case 'forbidden':
        http_response_code(403);
        $error_message = "禁止访问";
        break;
    case 'server_error':
        http_response_code(500);
        $error_message = "服务器内部错误";
        break;
    default:
        http_response_code(400);
        $error_message = "错误的请求";
}

// 输出错误页面
echo "<!DOCTYPE html>\n";
echo "<html>\n";
echo "<head>\n";
echo "    <title>错误 " . http_response_code() . " - " . $error_message . "</title>\n";
echo "</head>\n";
echo "<body>\n";
echo "    <h1>" . http_response_code() . " - " . $error_message . "</h1>\n";
echo "    <p>抱歉,请求的页面出现问题。</p>\n";
echo "</body>\n";
echo "</html>\n";
?>

示例 3:REST API 响应

在 REST API 中使用不同的 HTTP 状态码表示不同的操作结果。

<?php
// 设置响应头为JSON
header('Content-Type: application/json');

// 模拟API请求处理
$method = $_SERVER['REQUEST_METHOD'];
$request_data = json_decode(file_get_contents('php://input'), true);

// 处理不同的请求方法
switch ($method) {
    case 'GET':
        // 获取资源
        $resource_id = $_GET['id'] ?? null;

        if ($resource_id === '123') {
            http_response_code(200);
            echo json_encode([
                'id' => 123,
                'name' => '示例资源',
                'status' => 'active'
            ]);
        } else {
            http_response_code(404);
            echo json_encode([
                'error' => '资源未找到',
                'message' => '请求的资源不存在'
            ]);
        }
        break;

    case 'POST':
        // 创建资源
        if (!empty($request_data)) {
            http_response_code(201); // 201 Created
            echo json_encode([
                'id' => 456,
                'message' => '资源创建成功',
                'data' => $request_data
            ]);
        } else {
            http_response_code(400);
            echo json_encode([
                'error' => '无效的请求',
                'message' => '请求体不能为空'
            ]);
        }
        break;

    case 'PUT':
        // 更新资源
        http_response_code(200);
        echo json_encode([
            'message' => '资源更新成功',
            'data' => $request_data
        ]);
        break;

    case 'DELETE':
        // 删除资源
        http_response_code(204); // 204 No Content
        // 204状态码不返回任何内容
        break;

    default:
        http_response_code(405); // 405 Method Not Allowed
        header('Allow: GET, POST, PUT, DELETE');
        echo json_encode([
            'error' => '方法不允许',
            'message' => '只支持 GET, POST, PUT, DELETE 方法'
        ]);
}
?>

示例 4:与 header() 函数的比较

展示 http_response_code() 与使用 header() 函数设置状态码的区别。

<?php
// 使用 http_response_code() 设置状态码
// 更简洁,更容易理解
http_response_code(404);

// 使用 header() 函数设置状态码(传统方法)
// 需要指定完整的HTTP版本和状态消息
header("HTTP/1.1 404 Not Found");

// 两种方法的比较
echo "当前状态码(http_response_code): " . http_response_code() . "\n";

// 使用 header() 设置自定义状态消息
header("HTTP/1.1 418 I'm a teapot"); // RFC 2324

// 注意:http_response_code() 只接受数字状态码
// 它不能设置自定义状态消息
http_response_code(418); // 会设置状态码418,但消息可能是默认的

// 检查是否支持自定义状态消息
if (function_exists('header_register_callback')) {
    // 在某些配置下,可以注册回调来修改状态消息
    echo "支持自定义状态消息\n";
}

// 最佳实践:优先使用 http_response_code(),除非需要自定义状态消息
if ($custom_message_needed) {
    header("HTTP/1.1 499 Custom Status Message");
} else {
    http_response_code(499);
}
?>

示例 5:错误处理和调试

在实际应用中进行错误处理和调试。

<?php
/**
 * 安全地设置HTTP响应码
 * @param int $code HTTP状态码
 * @param string $message 可选的状态消息
 * @return bool 成功返回true,失败返回false
 */
function safe_http_response_code($code, $message = null) {
    // 检查状态码是否有效
    if ($code < 100 || $code > 599) {
        trigger_error("无效的HTTP状态码: $code", E_USER_WARNING);
        return false;
    }

    // 检查头信息是否已经发送
    if (headers_sent()) {
        trigger_error("无法设置HTTP状态码,头信息已经发送", E_USER_WARNING);
        return false;
    }

    // 如果有自定义消息,使用header()函数
    if ($message !== null) {
        $protocol = $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.1';
        header("$protocol $code $message");
    } else {
        // 否则使用http_response_code()
        http_response_code($code);
    }

    return true;
}

/**
 * 记录HTTP状态码变化
 */
class ResponseCodeLogger {
    private static $history = [];

    public static function set($code, $message = null) {
        $previous = http_response_code();

        if (safe_http_response_code($code, $message)) {
            self::$history[] = [
                'timestamp' => time(),
                'previous' => $previous,
                'new' => $code,
                'message' => $message,
                'backtrace' => debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)
            ];
            return true;
        }

        return false;
    }

    public static function getHistory() {
        return self::$history;
    }

    public static function displayHistory() {
        if (empty(self::$history)) {
            echo "没有状态码变化记录\n";
            return;
        }

        echo "<table border='1'>\n";
        echo "<tr><th>时间</th><th>之前</th><th>之后</th><th>消息</th><th>位置</th></tr>\n";

        foreach (self::$history as $entry) {
            echo "<tr>\n";
            echo "<td>" . date('Y-m-d H:i:s', $entry['timestamp']) . "</td>\n";
            echo "<td>" . $entry['previous'] . "</td>\n";
            echo "<td>" . $entry['new'] . "</td>\n";
            echo "<td>" . htmlspecialchars($entry['message'] ?? '默认') . "</td>\n";
            echo "<td>" . $entry['backtrace'][1]['file'] . ":" . $entry['backtrace'][1]['line'] . "</td>\n";
            echo "</tr>\n";
        }

        echo "</table>\n";
    }
}

// 使用示例
ResponseCodeLogger::set(200);
ResponseCodeLogger::set(404, "Custom Not Found Message");

// 模拟一些状态码变化
try {
    // 一些业务逻辑...
    if (!file_exists('somefile.txt')) {
        ResponseCodeLogger::set(404, "文件不存在");
    }

    // 更多的业务逻辑...
    ResponseCodeLogger::set(200); // 成功

} catch (Exception $e) {
    ResponseCodeLogger::set(500, "服务器错误: " . $e->getMessage());
}

// 显示历史记录
ResponseCodeLogger::displayHistory();
?>

注意事项

  • 头信息发送时机:必须在任何输出发送到浏览器之前调用 http_response_code(),否则可能无法设置成功。
  • 状态码范围:HTTP 状态码应该在 100-599 范围内。某些服务器可能不接受这个范围外的状态码。
  • 默认状态码:如果没有显式设置,默认的 HTTP 状态码是 200。
  • 返回值:当设置状态码时,函数返回之前的状态码。如果之前没有设置过状态码,则返回 true
  • 与 header() 的兼容性:http_response_code()header() 都可以设置状态码,但 http_response_code() 更简洁。
  • 状态消息:http_response_code() 不能设置自定义状态消息,而 header() 可以。
  • PHP 版本:该函数在 PHP 5.4.0 及更高版本中可用。对于更早的版本,需要使用 header() 函数。
  • 多次调用:可以多次调用此函数来改变状态码,但只有最后一个设置会生效。

常见问题

问题 解决方案
状态码设置失败 检查是否在输出之后调用函数。使用 headers_sent() 函数检查头信息是否已经发送。
返回 false 可能传递了无效的状态码,或者头信息已经发送。检查状态码是否在 100-599 范围内。
自定义状态消息 如果需要自定义状态消息,使用 header("HTTP/1.1 404 Custom Message") 而不是 http_response_code()
PHP 5.4 以下版本 使用 header() 函数替代,例如 header("HTTP/1.1 404 Not Found")
状态码不生效 某些服务器配置可能会覆盖 PHP 设置的状态码。检查服务器配置(如 .htaccess、nginx 配置等)。
获取不到当前状态码 如果没有设置过状态码,http_response_code() 可能返回 false。确保在获取之前已经设置了状态码。

相关函数