运行脚本时,我会遇到如下错误:

警告:无法修改标题信息-line 23/some/file.php中的(output started at /some/file.php:12)已发送标题

错误消息中提到的线路包含header()setcookie()个呼叫.

这可能是什么原因?如何修复它?

推荐答案

发送表头前无输出!

必须调用发送/修改HTTP头的函数101.

警告:无法修改标题信息-标题已发送(输出开始于脚本:行)

修改HTTP标头的一些功能包括:

输出可以是:

  • Unintentional:

  • Intentional:

    • printecho和其他产生输出的功能
    • 原始<html>节之前的<?php代码.

为什么会这样呢?

要理解为什么在输出之前必须发送头,这是必要的

HTTP/1.1 200 OK
Powered-By: PHP/5.3.7
Vary: Accept-Encoding
Content-Type: text/html; charset=utf-8

<html><head><title>PHP page output page</title></head>
<body><h1>Content</h1> <p>Some more output follows...</p>
and <a href="/"> <img src=internal-icon-delayed> </a>

页面/输出总是follows个页眉.PHP必须将 首先将标头发送到Web服务器.它只能这样做一次. 在双线之后,它再也不能修改它们了.

当PHP收到第一个输出(printecho<html>)时,它将

你如何找出过早输出发生在哪里?

header()警告包含所有相关信息,以 找到问题原因:

警告:无法修改标题信息-标题已由发送

这里的"第header()行"指的是header() invocation失败的脚本.

括号内的"output started at"更重要.

Typical causes:

  1. 打印,回声

    printecho语句的有意输出将终止发送HTTP头的机会.必须对应用程序流进行重组以避免这种情况.使用functions

    产生输出的函数包括

    • printechoprintfvprintf
    • trigger_error, ob_flush, ob_end_flush, var_dump, print_r
    • readfile, passthru, flush, imagepng, imagejpeg


    以及用户定义的函数.

  2. 原始HTML区域

    .php文件中未解析的HTML部分也是直接输出的.

    <!DOCTYPE html>
    <?php
        // Too late for headers already.
    

    使用模板方案将处理与输出逻辑分开.

    • 将表单处理代码置于脚本之上.
    • 使用临时字符串变量延迟消息.
    • The actual output logic and intermixed HTML output should follow last.

  3. Whitespace before <?php for "script.php line 1" warnings

    如果警告指的是内联输出100,那么它主要是 开始<?php令牌之前的前导whitespace、文本或HTML.

     <?php
    # There's a SINGLE space/newline before <? - Which already seals it.
    

    类似地,附加脚本或脚本部分也会出现这种情况:

    ?>
    
    <?php
    

    PHP实际上会占用结束标记后的single个换行符.但它不会 补偿移入此类间隙的多个换行符、制表符或空格.

  4. UTF-8物料 list

    换行符和空格本身就是一个问题.但也有"看不见的"

    特别是,图形编辑器和基于JAVA的IDE对于其 在场.他们没有将其可视化(受Unicode标准的约束). 但是,大多数程序员和控制台编辑器都是这样做的:

    joes editor showing UTF-8物料 list  placeholder, and MC editor a dot

    在那里,很容易在早期就认识到这个问题.其他编辑可能会指出

    beav hexeditor showing utf-8 bom

    一个简单的解决方法是将文本编辑器设置为将文件保存为"UTF-8(无BOM)"

    校正实用程序

    也有自动工具来判断和重写文本文件

    phptags  --whitespace  *.php
    

    在整个包含或项目目录中使用是安全的.

  5. Whitespace after ?>

    如果错误源被称为

    人们通常建议,尤其是对新手来说,使用?> PHP

  6. 错误源被称为"第0行未知"

    如果没有错误源,则通常是PHP扩展名或php.ini设置 是具体化的.

    • 有时是gzip流编码设置
    • But it could also be any doubly loaded extension= module generating an implicit PHP startup/warning message.

  7. 前面的错误消息

    如果其他PHP语句或表达式导致警告消息或 通知被打印出来,这也被算作过早输出.

    在这种情况下,您需要避免错误, 延迟语句执行,或使用例如 isset()@()- 当其中任何一个都不会妨碍以后的调试时.

没有错误消息

如果您每php.ini禁用error_reportingdisplay_errors, 那么就不会出现任何警告了.但是忽略错误并不能解决问题 离开.在过早输出之后,仍然无法发送标头.

因此,当header("Location: ...")个重定向静默失败时, 建议调查警告.使用两个简单的命令重新启用它们 在调用脚本之上:

error_reporting(E_ALL);
ini_set("display_errors", 1);

如果其他方法都失败了,那就是set_error_handler("var_dump");美元.

说到重定向头,你应该经常使用这样的习惯用法

exit(header("Location: /finished.html"));

优选地,甚至是打印用户消息的实用程序函数 在header()次故障的情况下.

输出缓冲作为一种解决方法

PHPs output buffering

  1. The output_buffering= setting nevertheless can help. Configure it in the php.ini or via .htaccess or even .user.ini on modern FPM/FastCGI setups.
    Enabling it will allow PHP to buffer output instead of passing it to the webserver instantly. PHP thus can aggregate HTTP headers.

  2. 它同样可以拨打ob_start();

    • 即使<?php ob_start(); ?>开始第一个脚本,空格或

    • 它可以隐藏HTML输出的空白.但一旦应用程序逻辑try 发送二进制内容(例如生成的图像),

    • 缓冲区的大小有限,如果保留默认值,很容易溢出.

因此,这两种方法都可能变得不可靠——尤其是在两种方法之间切换时

另见basic usage example

但它在另一台服务器上起作用了!?

如果你之前没有收到标题警告,那么output buffering php.ini setting

Checking with headers_sent()

如果出现以下情况,您始终可以使用headers_sent()进行探测 仍然有可能...发送标题.它对有条件打印很有用 信息或应用其他后备逻辑.

if (headers_sent()) {
    die("Redirect failed. Please click on this link: <a href=...>");
}
else{
    exit(header("Location: /user.php"));
}

有用的备用解决方案包括:

  • HTML <meta> tag

    如果您的应用程序在 struct 上很难修复,那么简单的(但是 有些不专业)允许重定向的方法是注入HTML <meta>个标签.可以通过以下方式实现重定向:

     <meta http-equiv="Location" content="http://example.com/">
    

    或稍加延迟:

     <meta http-equiv="Refresh" content="2; url=../target.html">
    

    当使用超过<head>节时,这会导致无效的HTML. 大多数浏览器仍然接受它.

  • JavaScript重定向

    作为替代方案,JavaScript重定向 可用于页面重定向:

     <script> location.replace("target.html"); </script>
    

    虽然这通常比<meta>解决方法更符合HTML, 它会导致对支持JavaScript的客户端的依赖.

但是,当使用真正的HTTP Header()时,这两种方法都会产生可接受的后备 呼叫失败.理想情况下,您应该始终将其与用户友好的消息相结合,并且 作为最后手段的可点击链接.(例如,这就是http_redirect() PECL扩展可以.)

Why setcookie() and session_start() are also affected

setcookie()session_start()都需要发送Set-Cookie: HTTP报头. 因此,适用相同的条件,并且将生成类似的错误消息 用于过早输出的情况.

(当然,他们还会受到浏览器中禁用的cookie的影响 甚至是委托书问题.会话功能显然也依赖于免费 磁盘空间和其他php.ini设置等)

进一步链接

Php相关问答推荐

根据订单元数据向特定WooCommerce邮箱通知添加一些文本

提交表格后的重定向不起作用

PHP -使用preg_match在字符串中进行匹配

419注册期间Laravel 11中的错误

Laravel 10查询中的多个where子句

Symfony Monolog:使用多个格式化程序

用于计算付款费用的WooCommerce管理编辑产品中的自定义复选框

使用随机生成器在MYSQL中创建唯一ID-定义一个数组来存储已知ID是否安全

即使在WooCommerce购物车中添加了两次产品,也要将所有项目设置为空白行

标签打印机的 CSS

AWS S3:当对象名称包含 % 时复制对象失败并出现错误 - 无效的复制源编码

图片上传成功

Laravel 添加到经过身份验证的用户的数据将应用于每个查询

通过存储库检索 Blade 上的单值数据 出错

URL中包含"&"与DirectoryIterator不兼容

WooCommerce – 在新订单邮箱通知中显示产品分类计数

如何在 Process facade 中转义特殊字符?

转发和非转发呼叫 - 后期静态绑定

Eloquent 的模型更新了它应该 laravel php 的更多行

即使密码匹配,密码处理程序也会返回错误