警告:无法修改标头信息 - 已发送的标头

时间:2010-07-15 22:28:24

标签: php header

请救救我。我知道这个问题已被多次询问,但是,我似乎无法找到与我的情况相关的解决方案。

问题:Warning: Cannot modify header information - headers already sent by (output started at /.../Sites/st.ambulance/resources/views/login.view.php:32) in /.../Sites/st.ambulance/resources/controllers/tables_.php on line 47

这是第32行的代码块:

      <label>Month</label>
        <select name="dob_month">
            <?php for($i=0,$j=1;$i<sizeof($month);$i++,$j++){ ?>
                <option value="<?php h($j) ?>"><?php h($month[$i]) ?></option>  //line 32
            <?php } ?>
        </select>

h函数的定义:

function h($s){
    echo(htmlspecialchars($s,ENT_QUOTES));
}

这是tables_.php:

<?php
 $error = "";
 if(isset($_POST['guest_tables'])){
 if(isset($_SESSION['logged_in']) && $_SESSION['logged_in']){
    $guest = array();
    $volunteer = array();

    $guest = isset($_POST['guest']) ? $_POST['guest'] : null;
    $volunteer = isset($_POST['volunteer']) ? $_POST['volunteer'] : null;

    $seat_array = array($volunteer['seat_no'].$volunteer['table']);
    $seat_count = 0;
    $table_seat_error = "";

    if($form->is_seatOccupied($volunteer['table'],$volunteer['seat_no']) != "")
            $table_seat_error .= "Seat (".$volunteer['seat_no'].")
                at table (".$volunteer['table'].") is currently occupied";

    if($_SESSION['no_guests'] >= 1){
        if($guest && $volunteer){
            foreach($guest as $gue){

                $seat_table = $gue['seat_no'].$gue['table'];
                for($h=0;$h<sizeof($seat_array);$h++){
                    if($seat_table == $seat_array[$h] )
                        $seat_count = $seat_count + 1;
                }
                if($form->is_seatOccupied($gue['table'], $gue['seat_no']) != "")
                            $table_seat_error .= "Seat (".$gue['seat_no'].")
                                at table (".$gue['table'].") is currently occupied";

                $seat_array[] = $seat_table;
            }
            if($seat_count == 0){
                if($table_seat_error == ""){
                    for($d=0;$d<$_SESSION['no_guests'];$d++){
                        $_SESSION['guests'][$d]['table'] = $guest[$d]['table'];
                        $_SESSION['guests'][$d]['seat'] = $guest[$d]['seat_no'];
                    }

                    $_SESSION['volunteer']['table'] = $volunteer['table'];
                    $_SESSION['volunteer']['seat'] = $volunteer['seat_no'];

                    $form->set_guests($_SESSION['guests']);
                    $form->set_volunteer($_SESSION['volunteer']);

                    header('location: /branch/menus.php'); //line 47
                    exit();
                }
                else{
                    $error = $table_seat_error;
                }
            }
            else{
                $error = "You have selected the same seat for two or more
                    people: one person, per seat, per table. Only.";
            }
        }
    }
    else{

        $_SESSION['volunteer']['table'] = $volunteer['table'];
        $_SESSION['volunteer']['seat'] = $volunteer['seat_no'];

        if(!$form->is_seatOccupied($_SESSION['volunteer']['table'],
                $_SESSION['volunteer']['seat']) != ""){
            $form->set_volunteer($_SESSION['volunteer']);

            header('location: /branch/menus.php');
            exit();

            }
      }
    }
  }
 ?>

编辑:知道我正在尝试在一个页面上处理多个表单会有帮助吗?

2 个答案:

答案 0 :(得分:3)

第47行修改响应标题:

header('location: /branch/menus.php'); //line 47

第47行无法执行,因为标题已经发送,这恰好发生在第32行。第32行发生的一切是PHP确定响应中有足够的内容开始将其发送回浏览器。

通常,如果你想修改标题(无论你在第47行做什么),你需要在文件的最开头

现在是了解MVC design pattern的好时机 - 它将在未来消除此问题的可能性。在MVC中,Controller首先执行,并为View准备一切。因此,您可以在Controller中修改所需的标题,直到处理视图期间或之后才会发送它们。

编辑:看起来你正在使用MVC,但不知何故你的视图在控制器启动(或者可能已完成)之前正在执行......这不应该发生!遗憾的是,您发布的代码并没有说明如何访问控制器或视图......但是它们是无序访问的。

正如TRiG在下面的评论中指出的那样,您可能希望在第47行之后插入exit()语句,如下所示:

header('location: /branch/menus.php'); //line 47
exit();

这将使服务器立即将位置重定向发送到浏览器,并且请求/响应周期完成。 所有您的header('Location: ...');来电应紧跟exit();。这并不能解决手头的问题,但这非常重要。

答案 1 :(得分:0)

打开输出缓冲,找到php.ini并查找/取消注释/更改/添加以下行:

output_buffering = On

编辑并在某些初始包含中添加一行ob_start();,例如一些常见的init.php或database.php
编辑^ 2:不需要ob_start(已经?);这工作,保存为test.php和请求。眼见为实。

Output has started
<?php
    header("Content-Type: text/plain");
?>

关键是在HTTP中,服务器的响应由两部分组成:标题和正文。

标题包含有关内容,连接等的信息,例如内容的类型,例如

Content-Type: text/html
or
Content-Type: image/jpeg

表示它是html或jpg。没有它,浏览器将无法确定如何处理内容。当然,一旦PHP必须开始输出响应的正文部分,就无法更改标题。因此,您可以在发出正文的任何字节之前先执行任何与标题相关的操作,或者您可以指示php保持它的呼吸并仅在脚本完成时释放正文,或者当您这么说时。这就是他们所说的输出缓冲。