PHP header() 函数

header() 函数用于向客户端发送原始的 HTTP 头。

HTTP 头是服务器在发送 HTML 内容之前发送到浏览器的信息。它们可以用于重定向、设置内容类型、控制缓存、设置 cookie 等。

重要:header() 函数必须在任何实际输出之前调用,包括 HTML 标签、空格、换行符或 PHP 输出(如 echo、print 等)。否则会导致 "headers already sent" 错误。

语法

header ( string $header [, bool $replace = true [, int $response_code ]] ) : void

参数

参数 类型 描述
$header string 必需的。要发送的 HTTP 头字符串。格式通常为 "Header-Name: value"。
特殊值:
  • "Location: URL" - 重定向到指定 URL
  • "Content-Type: type" - 设置内容类型
  • "HTTP/1.1 404 Not Found" - 发送 HTTP 状态码
$replace bool 可选的。指定是否替换之前发送的相同类型的头。
  • true (默认) - 替换相同类型的头
  • false - 允许发送多个相同类型的头
$response_code int 可选的。强制指定 HTTP 响应码。这个参数只在 $header 不为空时有效。

返回值

该函数没有返回值。

常见 HTTP 状态码

状态码 描述 使用示例
200 OK - 请求成功 header("HTTP/1.1 200 OK");
301 Moved Permanently - 永久重定向 header("HTTP/1.1 301 Moved Permanently");
302 Found - 临时重定向 header("HTTP/1.1 302 Found");
304 Not Modified - 资源未修改 header("HTTP/1.1 304 Not Modified");
400 Bad Request - 请求无效 header("HTTP/1.1 400 Bad Request");
401 Unauthorized - 需要认证 header("HTTP/1.1 401 Unauthorized");
403 Forbidden - 禁止访问 header("HTTP/1.1 403 Forbidden");
404 Not Found - 资源未找到 header("HTTP/1.1 404 Not Found");
500 Internal Server Error - 服务器内部错误 header("HTTP/1.1 500 Internal Server Error");

示例

示例 1:重定向到另一个页面

最常见的用法是重定向用户到另一个页面。

<?php
// 重定向到另一个页面
header("Location: https://www.example.com/");
exit; // 确保重定向后立即停止脚本执行

// 或者使用完整 URL
header("Location: /newpage.php");
exit;

// 带有状态码的重定向
header("Location: /newpage.php", true, 301);
exit;
?>

示例 2:设置内容类型

设置响应的内容类型,例如输出 JSON、XML 或下载文件。

<?php
// 输出 JSON
header("Content-Type: application/json");
echo json_encode(['name' => 'John', 'age' => 30]);

// 输出 XML
header("Content-Type: text/xml");
echo '<?xml version="1.0" encoding="UTF-8"?>';
echo '<note><to>John</to><from>Jane</from></note>';

// 输出纯文本
header("Content-Type: text/plain");
echo "This is plain text";

// 输出 HTML(默认)
header("Content-Type: text/html; charset=UTF-8");
?>

示例 3:文件下载

强制浏览器下载文件而不是显示它。

<?php
$filename = "example.pdf";
$filepath = "/path/to/files/" . $filename;

// 检查文件是否存在
if (file_exists($filepath)) {
    // 设置适当的头信息
    header("Content-Type: application/octet-stream");
    header("Content-Disposition: attachment; filename=\"" . basename($filepath) . "\"");
    header("Content-Length: " . filesize($filepath));

    // 清空输出缓冲区
    flush();

    // 读取文件并输出
    readfile($filepath);
    exit;
} else {
    header("HTTP/1.1 404 Not Found");
    echo "File not found";
}
?>

示例 4:控制缓存

控制浏览器和代理服务器的缓存行为。

<?php
// 禁止缓存当前页面
header("Cache-Control: no-cache, no-store, must-revalidate"); // HTTP 1.1
header("Pragma: no-cache"); // HTTP 1.0
header("Expires: 0"); // 代理服务器

// 设置缓存时间(1小时)
header("Cache-Control: max-age=3600");
header("Expires: " . gmdate("D, d M Y H:i:s", time() + 3600) . " GMT");

// 设置最后修改时间
$last_modified = filemtime(__FILE__);
header("Last-Modified: " . gmdate("D, d M Y H:i:s", $last_modified) . " GMT");

// 检查客户端缓存是否最新
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) &&
    strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $last_modified) {
    header("HTTP/1.1 304 Not Modified");
    exit;
}
?>

示例 5:设置自定义头

发送自定义的 HTTP 头。

<?php
// 设置 CORS(跨域资源共享)头
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type, Authorization");

// 设置自定义头
header("X-Powered-By: PHP/7.4");
header("X-Content-Type-Options: nosniff");

// 多个相同类型的头(设置 $replace 为 false)
header("Set-Cookie: name=value; path=/", false);
header("Set-Cookie: name2=value2; path=/", false);
?>

示例 6:处理 AJAX 请求

为 AJAX 请求设置适当的响应头。

<?php
// 检查是否为 AJAX 请求
$is_ajax = !empty($_SERVER['HTTP_X_REQUESTED_WITH']) &&
           strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';

if ($is_ajax) {
    // 设置 JSON 响应
    header("Content-Type: application/json");

    $response = [
        'success' => true,
        'message' => '请求成功',
        'data' => ['id' => 123, 'name' => 'John Doe']
    ];

    echo json_encode($response);
    exit;
}

// 对于非 AJAX 请求,返回 HTML
header("Content-Type: text/html; charset=UTF-8");
?>

示例 7:错误页面

设置错误页面的 HTTP 状态码。

<?php
// 404 错误页面
header("HTTP/1.1 404 Not Found");
header("Content-Type: text/html; charset=UTF-8");
?>
<!DOCTYPE html>
<html>
<head>
    <title>404 Not Found</title>
</head>
<body>
    <h1>404 - Page Not Found</h1>
    <p>The page you are looking for does not exist.</p>
</body>
</html>

注意事项

  • 输出前调用:header() 必须在任何输出之前调用,包括空格和换行符。使用输出缓冲(ob_start())可以解决这个问题。
  • exit 或 die:在发送重定向头后,通常应该立即调用 exit 或 die 来停止脚本执行。
  • 相对 URL:Location 头可以使用相对 URL,但最好使用绝对 URL。
  • 状态码:某些状态码(如 301、302)会自动引起重定向。
  • 多次调用:可以多次调用 header() 来发送多个头。
  • 已发送头信息:使用 headers_sent() 函数检查头信息是否已经发送。
  • 文件编码:确保 PHP 文件保存为无 BOM 的 UTF-8 格式,避免在文件开头添加不可见字符。
  • 性能:过多的 HTTP 头可能会影响性能。

常见问题

问题 解决方案
"headers already sent" 错误
  • 确保在 header() 之前没有输出任何内容
  • 检查文件开头是否有空格或空行
  • 检查是否有 UTF-8 BOM 标记
  • 使用输出缓冲:ob_start();
重定向不起作用
  • 确保在 header("Location: ...") 后调用 exit
  • 检查 URL 是否正确
  • 确保没有输出在重定向之前发送
设置 cookie 失败
  • 确保在设置 cookie 之前没有输出
  • 检查 setcookie() 函数的参数是否正确
  • 注意 cookie 的路径和域名设置
文件下载损坏
  • 确保在发送文件内容之前发送了正确的头信息
  • 使用 readfile() 而不是 echo file_get_contents()
  • 检查文件路径是否正确

实用技巧

1. 检查头是否已发送
<?php
if (!headers_sent()) {
    header("Location: /newpage.php");
    exit;
} else {
    echo "无法重定向,头信息已发送";
}
?>
2. 使用输出缓冲
<?php
ob_start(); // 开始输出缓冲

// 这里可以有输出
echo "Some output";

// 稍后设置头信息
header("Content-Type: application/json");

// 获取缓冲内容并发送
ob_end_flush();
?>
3. 设置多个相同类型的头
<?php
// 设置多个 cookie
header("Set-Cookie: name=value1", false);
header("Set-Cookie: name2=value2", false);

// 设置多个自定义头
header("X-Custom-Header: Value1", false);
header("X-Custom-Header: Value2", false);
?>

相关函数