วิธีแก้ไขข้อผิดพลาด“ ส่วนหัวที่ส่งไปแล้ว” ใน PHP

Nov 07 2011

เมื่อเรียกใช้สคริปต์ของฉันฉันได้รับข้อผิดพลาดหลายประการดังนี้:

คำเตือน: ไม่สามารถแก้ไขข้อมูลส่วนหัว - ส่วนหัวที่ส่งไปแล้ว ( เอาต์พุตเริ่มต้นที่ /some/file.php:12 ) ใน/some/file.phpในบรรทัดที่ 23

บรรทัดที่กล่าวถึงในข้อความแสดงข้อผิดพลาดประกอบด้วยheader()และการsetcookie()โทร

อะไรคือสาเหตุของเรื่องนี้? แล้วแก้ไขยังไง?

คำตอบ

3066 mario Nov 07 2011 at 00:45

ไม่มีเอาต์พุตก่อนส่งส่วนหัว!

ฟังก์ชั่นที่ส่ง / ปรับเปลี่ยนส่วนหัว HTTP จะต้องถูกเรียกก่อนที่จะส่งออกใด ๆ ที่จะทำ summary ⇊มิฉะนั้นการโทรล้มเหลว:

คำเตือน: ไม่สามารถแก้ไขข้อมูลส่วนหัว - ส่งส่วนหัวไปแล้ว (เอาต์พุตเริ่มต้นที่script: line )

ฟังก์ชันบางอย่างที่แก้ไขส่วนหัว HTTP ได้แก่ :

  • header / header_remove
  • session_start / session_regenerate_id
  • setcookie / setrawcookie

เอาต์พุตสามารถ:

  • โดยไม่ได้ตั้งใจ:

    • เว้นวรรคก่อน<?phpหรือหลัง?>
    • UTF-8 Byte มาร์คสั่งซื้อสินค้าโดยเฉพาะ
    • ข้อความแสดงข้อผิดพลาดหรือประกาศก่อนหน้านี้
  • เจตนา:

    • print, echoและฟังก์ชั่นอื่น ๆ การผลิตการส่งออก
    • รหัส<html>ก่อนหน้าของส่วนดิบ<?php

ทำไมมันถึงเกิดขึ้น?

เพื่อให้เข้าใจว่าเหตุใดจึงต้องส่งส่วนหัวก่อนที่จะส่งออกจึงจำเป็นต้องดูการตอบสนองHTTPทั่วไป สคริปต์ PHP ส่วนใหญ่สร้างเนื้อหา HTML แต่ยังส่งชุดของส่วนหัว HTTP / CGI ไปยังเว็บเซิร์ฟเวอร์:

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>

เพจ / เอาต์พุตจะตามหลังส่วนหัวเสมอ PHP ต้องส่งส่วนหัวไปยังเว็บเซิร์ฟเวอร์ก่อน ทำได้เพียงครั้งเดียว หลังจากการแตกไลน์สองครั้งจะไม่สามารถแก้ไขได้อีกต่อไป

เมื่อ PHP ได้รับการส่งออกครั้งแรก ( print, echo, <html>) มันจะล้างหัวเก็บรวบรวมทั้งหมด หลังจากนั้นก็สามารถส่งเอาต์พุตทั้งหมดที่ต้องการได้ แต่การส่งส่วนหัว HTTP เพิ่มเติมนั้นเป็นไปไม่ได้แล้ว

คุณจะทราบได้อย่างไรว่าผลผลิตก่อนกำหนดเกิดขึ้นได้อย่างไร?

header()เตือนมีข้อมูลที่เกี่ยวข้องทั้งหมดเพื่อหาสาเหตุปัญหา:

คำเตือน: ไม่สามารถแก้ไขข้อมูลส่วนหัว - ส่วนหัวที่ส่งไปแล้ว(เอาต์พุตเริ่มต้นที่ / www / usr2345 / htdocs / auth.php: 52 ) ใน /www/usr2345/htdocs/index.php ในบรรทัด 100

ในที่นี้ "บรรทัดที่ 100" หมายถึงสคริปต์ที่การheader() เรียกใช้ล้มเหลว

หมายเหตุ " เอาต์พุตเริ่มต้นที่ " ภายในวงเล็บมีความสำคัญมากกว่า มันหมายถึงแหล่งที่มาของเอาต์พุตก่อนหน้านี้ ในตัวอย่างนี้มันauth.phpและบรรทัด 52นั่นคือจุดที่คุณต้องมองหาผลผลิตก่อนกำหนด

สาเหตุทั่วไป:

  1. พิมพ์เสียงสะท้อน

    การส่งออกโดยเจตนาจากprintและechoคำสั่งจะยุติโอกาสในการส่งส่วนหัว HTTP ขั้นตอนการสมัครต้องได้รับการปรับโครงสร้างใหม่เพื่อหลีกเลี่ยงสิ่งนั้น ใช้ฟังก์ชันและโครงร่างเทมเพลต ตรวจสอบให้แน่ใจheader()ว่ามีการโทรก่อนที่จะเขียนข้อความ

    ฟังก์ชั่นที่สร้างผลลัพธ์ ได้แก่

    • print, echo, printf,vprintf
    • trigger_error, ob_flush, ob_end_flush, var_dump,print_r
    • readfile, passthru, flush, imagepng,imagejpeg


    ท่ามกลางฟังก์ชันอื่น ๆ และฟังก์ชันที่ผู้ใช้กำหนดเอง

  2. พื้นที่ HTML ดิบ

    ส่วน HTML ที่ไม่ได้แยกวิเคราะห์ใน.phpไฟล์เป็นเอาต์พุตโดยตรงเช่นกัน เงื่อนไขของสคริปต์ที่จะทริกเกอร์การheader()โทรจะต้องสังเกตก่อนบล็อกดิบใด ๆ<html>

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

    ใช้โครงร่างเทมเพลตเพื่อแยกการประมวลผลออกจากตรรกะเอาต์พุต

    • วางโค้ดการประมวลผลแบบฟอร์มบนสคริปต์
    • ใช้ตัวแปรสตริงชั่วคราวเพื่อเลื่อนข้อความ
    • ลอจิกเอาต์พุตจริงและเอาต์พุต HTML แบบผสมควรเป็นไปตามลำดับสุดท้าย

  3. <?phpเว้นวรรคก่อนสำหรับคำเตือน"script.php line 1 "

    หากคำเตือนอ้างถึงผลลัพธ์ในบรรทัดแสดง1ว่าส่วนใหญ่เป็นช่องว่างข้อความหรือ HTML ก่อน<?phpโทเค็นเปิด

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

    ในทำนองเดียวกันอาจเกิดขึ้นสำหรับสคริปต์ต่อท้ายหรือส่วนของสคริปต์:

    ?>
    
    <?php
    

    PHP กินบรรทัดเดียวหลังจากปิดแท็ก แต่จะไม่ชดเชยการขึ้นบรรทัดใหม่หรือแท็บหรือช่องว่างหลายรายการที่เลื่อนเข้ามาในช่องว่างดังกล่าว

  4. UTF-8 BOM

    การแบ่งเส้นและการเว้นวรรคเพียงอย่างเดียวอาจเป็นปัญหาได้ แต่ยังมีลำดับอักขระที่ "มองไม่เห็น" ซึ่งอาจทำให้เกิดสิ่งนี้ได้ UTF-8 BOM (Byte-Order-Mark)ที่มีชื่อเสียงที่สุดซึ่งไม่ได้แสดงโดยโปรแกรมแก้ไขข้อความส่วนใหญ่ เป็นลำดับไบต์EF BB BFซึ่งเป็นทางเลือกและซ้ำซ้อนสำหรับเอกสารที่เข้ารหัส UTF-8 อย่างไรก็ตาม PHP ต้องถือว่าเป็นเอาต์พุตดิบ อาจแสดงเป็นอักขระในเอาต์พุต (หากไคลเอ็นต์ตีความเอกสารเป็นละติน -1) หรือ "ขยะ" ที่คล้ายกัน

    โดยเฉพาะอย่างยิ่งโปรแกรมแก้ไขกราฟิกและ IDE ที่ใช้ Java จะไม่หลงลืมการมีอยู่ พวกเขาไม่เห็นภาพ (บังคับโดยมาตรฐาน Unicode) อย่างไรก็ตามโปรแกรมเมอร์และบรรณาธิการคอนโซลส่วนใหญ่ทำ:

    การรับรู้ปัญหาตั้งแต่เนิ่นๆจึงเป็นเรื่องง่าย บรรณาธิการอื่น ๆ อาจระบุการแสดงตนในเมนูไฟล์ / การตั้งค่า (Notepad ++ บน Windows สามารถระบุและแก้ไขปัญหาที่เกิดขึ้น ) ตัวเลือกในการตรวจสอบการปรากฏ BOMs ก็คือการหันไปยังHexEditor โดยทั่วไปในระบบ * nix hexdumpจะพร้อมใช้งานหากไม่ใช่ตัวแปรกราฟิกที่ช่วยลดความซับซ้อนในการตรวจสอบปัญหาเหล่านี้และปัญหาอื่น ๆ :

    วิธีแก้ไขง่ายๆคือตั้งค่าโปรแกรมแก้ไขข้อความให้บันทึกไฟล์เป็น "UTF-8 (no BOM)" หรือระบบการตั้งชื่อที่คล้ายกัน บ่อยครั้งที่ผู้มาใหม่มักใช้วิธีสร้างไฟล์ใหม่และเพียงแค่คัดลอกและวางโค้ดก่อนหน้านี้กลับเข้าไป

    ยูทิลิตี้การแก้ไข

    นอกจากนี้ยังมีเครื่องมืออัตโนมัติในการตรวจสอบและเขียนไฟล์ข้อความอีกครั้ง ( sed/awkหรือrecode) สำหรับ PHP เฉพาะมีของtidierphptags แท็ก มันเขียนแท็กปิดและเปิดใหม่เป็นรูปแบบยาวและสั้น แต่ยังแก้ไขช่องว่างนำหน้าและต่อท้ายปัญหา Unicode และ UTF-x BOM ได้อย่างง่ายดาย:

    phptags  --whitespace  *.php
    

    เป็นสิ่งที่ดีที่จะใช้กับไดเร็กทอรีรวมหรือโปรเจ็กต์ทั้งหมด

  5. ช่องว่างหลัง ?>

    หากแหล่งที่มาของข้อผิดพลาดถูกกล่าวถึงอยู่หลังการปิด?>นี่คือที่ที่มีการเขียนช่องว่างหรือข้อความดิบ เครื่องหมายปิดท้าย PHP ไม่ยุติการเรียกใช้สคริปต์ในจุดนี้ อักขระข้อความ / เว้นวรรคใด ๆ หลังจากนั้นจะถูกเขียนเป็นเนื้อหาของหน้า

    โดยเฉพาะอย่างยิ่งสำหรับผู้มาใหม่?>ควรละเว้นแท็กปิด PHP ต่อท้าย ซึ่งเป็นการหลีกเลี่ยงกรณีเหล่านี้เพียงเล็กน้อย ( include()dสคริปต์โดยทั่วไปมักเป็นตัวการ)

  6. แหล่งที่มาของข้อผิดพลาดระบุว่า "ไม่ทราบที่บรรทัด 0"

    โดยทั่วไปจะเป็นนามสกุล PHP หรือการตั้งค่า php.ini หากไม่มีแหล่งที่มาของข้อผิดพลาดเป็นคอนกรีต

    • ในบางครั้งอาจเป็นการgzipตั้งค่าการเข้ารหัสสตรีมหรือไฟล์ob_gzhandler .
    • แต่อาจเป็นextension=โมดูลที่โหลดเป็นสองเท่าซึ่งสร้างข้อความเริ่มต้น / คำเตือน PHP โดยปริยาย

  7. ข้อความแสดงข้อผิดพลาดก่อนหน้า

    หากคำสั่งหรือนิพจน์ PHP อื่นทำให้เกิดข้อความเตือนหรือการแจ้งเตือนถูกพิมพ์ออกมาสิ่งนั้นก็นับเป็นการส่งออกก่อนกำหนดเช่นกัน

    ในกรณีนี้คุณจำเป็นต้องหลีกเลี่ยงข้อผิดพลาดชะลอการดำเนินการคำสั่งหรือระงับข้อความด้วยเช่นisset()หรือ@()- เมื่ออย่างใดอย่างหนึ่งไม่ขัดขวางการดีบักในภายหลัง

ไม่มีข้อความแสดงข้อผิดพลาด

หากคุณมีerror_reportingหรือdisplay_errorsปิดใช้งานphp.iniจะไม่มีคำเตือนปรากฏขึ้น แต่การเพิกเฉยต่อข้อผิดพลาดจะไม่ทำให้ปัญหาหมดไป ยังไม่สามารถส่งส่วนหัวได้หลังจากเอาต์พุตก่อนกำหนด

ดังนั้นเมื่อการheader("Location: ...")เปลี่ยนเส้นทางล้มเหลวโดยไม่ได้ตั้งใจขอแนะนำให้ตรวจสอบคำเตือน เปิดใช้งานอีกครั้งด้วยคำสั่งง่ายๆสองคำสั่งบนสคริปต์การเรียกใช้:

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

หรือset_error_handler("var_dump");ถ้าทุกอย่างล้มเหลว

เมื่อพูดถึงส่วนหัวการเปลี่ยนเส้นทางคุณควรใช้สำนวนเช่นนี้สำหรับพา ธ โค้ดขั้นสุดท้าย:

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

ควรเป็นฟังก์ชันยูทิลิตี้ซึ่งพิมพ์ข้อความผู้ใช้ในกรณีที่เกิดheader()ความล้มเหลว

การบัฟเฟอร์เอาต์พุตเป็นวิธีแก้ปัญหาชั่วคราว

PHPs บัฟเฟอร์เอาต์พุตเป็นวิธีแก้ปัญหาเพื่อบรรเทาปัญหานี้ มักจะทำงานได้อย่างน่าเชื่อถือ แต่ไม่ควรแทนที่การจัดโครงสร้างแอปพลิเคชันที่เหมาะสมและแยกเอาต์พุตออกจากตรรกะการควบคุม จุดประสงค์ที่แท้จริงคือลดการถ่ายโอนที่เป็นก้อนไปยังเว็บเซิร์ฟเวอร์ให้น้อยที่สุด

  1. output_buffering=การตั้งค่ายังคงสามารถช่วย กำหนดค่าในphp.iniหรือผ่าน. htaccessหรือแม้แต่. user.iniบนการตั้งค่า FPM / FastCGI ที่ทันสมัย
    การเปิดใช้งานจะทำให้ PHP สามารถบัฟเฟอร์เอาต์พุตแทนที่จะส่งผ่านไปยังเว็บเซิร์ฟเวอร์ได้ทันที PHP จึงสามารถรวมส่วนหัว HTTP

  2. นอกจากนี้ยังสามารถมีส่วนร่วมกับการเรียกไปที่ob_start();ด้านบนสคริปต์การเรียกร้อง อย่างไรก็ตามมีความน่าเชื่อถือน้อยกว่าด้วยเหตุผลหลายประการ:

    • แม้ว่า<?php ob_start(); ?>จะเริ่มต้นสคริปต์แรกช่องว่างหรือ BOM อาจได้รับการสับก่อนการกระทำมันไม่ได้ผล

    • สามารถปกปิดช่องว่างสำหรับเอาต์พุต HTML แต่ทันทีที่ตรรกะของแอปพลิเคชันพยายามส่งเนื้อหาไบนารี (เช่นรูปภาพที่สร้างขึ้น) เอาต์พุตภายนอกที่บัฟเฟอร์จะกลายเป็นปัญหา (จำเป็นต้องob_clean()เป็นวิธีแก้ปัญหาที่ยาวขึ้น)

    • บัฟเฟอร์มีขนาด จำกัด และสามารถบุกรุกได้ง่ายเมื่อปล่อยให้เป็นค่าเริ่มต้น และนั่นไม่ใช่เหตุการณ์ที่เกิดขึ้นได้ยากเช่นกันยากที่จะติดตามเมื่อมันเกิดขึ้น

ดังนั้นแนวทางทั้งสองจึงไม่น่าเชื่อถือโดยเฉพาะอย่างยิ่งเมื่อสลับระหว่างการตั้งค่าการพัฒนาและ / หรือเซิร์ฟเวอร์ที่ใช้งานจริง ด้วยเหตุนี้การบัฟเฟอร์เอาต์พุตจึงถูกพิจารณาอย่างกว้างขวางว่าเป็นเพียงแค่ไม้ค้ำยัน / วิธีแก้ปัญหาอย่างเคร่งครัด

ดูตัวอย่างการใช้งานพื้นฐานในคู่มือและข้อดีข้อเสียเพิ่มเติม:

  • บัฟเฟอร์เอาต์พุตคืออะไร?
  • เหตุใดจึงต้องใช้การบัฟเฟอร์เอาต์พุตใน PHP
  • การใช้บัฟเฟอร์เอาต์พุตถือเป็นการปฏิบัติที่ไม่ดีหรือไม่?
  • ใช้กรณีสำหรับการบัฟเฟอร์เอาต์พุตเป็นวิธีแก้ปัญหาที่ถูกต้องสำหรับ "ส่วนหัวที่ส่งไปแล้ว"

แต่มันทำงานบนเซิร์ฟเวอร์อื่น!?

หากคุณไม่ได้รับคำเตือนส่วนหัวมาก่อนแสดงว่าการตั้งค่า php.ini บัฟเฟอร์เอาต์พุตมีการเปลี่ยนแปลง มีแนวโน้มว่าจะไม่ได้กำหนดค่าบนเซิร์ฟเวอร์ปัจจุบัน / เซิร์ฟเวอร์ใหม่

กำลังตรวจสอบกับ headers_sent()

คุณสามารถใช้headers_sent()เพื่อตรวจสอบได้ตลอดเวลาว่ายัง ... ส่งส่วนหัวได้หรือไม่ ซึ่งมีประโยชน์ในการพิมพ์ข้อมูลตามเงื่อนไขหรือใช้ตรรกะทางเลือกอื่น ๆ

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

วิธีแก้ปัญหาทางเลือกที่เป็นประโยชน์ ได้แก่ :

  • <meta>แท็กHTML

    หากแอปพลิเคชันของคุณมีโครงสร้างที่แก้ไขได้ยากวิธีที่ง่าย (แต่ค่อนข้างไม่เป็นมืออาชีพ) ในการอนุญาตให้เปลี่ยนเส้นทางคือการแทรก<meta>แท็กHTML การเปลี่ยนเส้นทางสามารถทำได้ด้วย:

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

    หรือด้วยการหน่วงเวลาสั้น ๆ :

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

    สิ่งนี้นำไปสู่ ​​HTML ที่ไม่ถูกต้องเมื่อใช้ผ่าน<head>ส่วนนี้ เบราว์เซอร์ส่วนใหญ่ยังรับได้

  • เปลี่ยนเส้นทาง JavaScript

    อีกทางเลือกหนึ่งคือสามารถใช้การเปลี่ยนเส้นทาง JavaScriptสำหรับการเปลี่ยนเส้นทางหน้า:

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

    แม้ว่าสิ่งนี้มักจะเป็นไปตาม HTML มากกว่า<meta>วิธีแก้ปัญหา แต่ก็ต้องพึ่งพาไคลเอ็นต์ที่สามารถใช้ JavaScript ได้

อย่างไรก็ตามทั้งสองวิธีสร้างทางเลือกที่ยอมรับได้เมื่อการเรียกส่วนหัว HTTP () ของแท้ล้มเหลว ตามหลักการแล้วคุณมักจะรวมสิ่งนี้เข้ากับข้อความที่ใช้งานง่ายและลิงก์ที่คลิกได้เป็นทางเลือกสุดท้าย (ซึ่งเป็นสิ่งที่ส่วนขยายhttp_redirect () PECL ทำ)

ทำไมsetcookie()และsession_start()ยังได้รับผลกระทบ

ทั้งสองอย่างsetcookie()และsession_start()จำเป็นต้องส่งSet-Cookie:ส่วนหัว HTTP ดังนั้นจึงใช้เงื่อนไขเดียวกันและข้อความแสดงข้อผิดพลาดที่คล้ายกันจะถูกสร้างขึ้นสำหรับสถานการณ์เอาต์พุตก่อนกำหนด

(แน่นอนว่าพวกเขาได้รับผลกระทบจากคุกกี้ที่ปิดใช้งานในเบราว์เซอร์หรือแม้แต่ปัญหาเกี่ยวกับพร็อกซีเห็นได้ชัดว่าฟังก์ชันเซสชันขึ้นอยู่กับเนื้อที่ว่างในดิสก์และการตั้งค่า php.ini อื่น ๆ เป็นต้น)

ลิงค์เพิ่มเติม

  • Google มีรายการยาวของการอภิปรายที่คล้ายกัน
  • และแน่นอนว่ามีการครอบคลุมกรณีเฉพาะจำนวนมากใน Stack Overflow ด้วยเช่นกัน
  • คำถามที่พบบ่อยของ Wordpress อธิบายฉันจะแก้ปัญหาส่วนหัวที่ส่งคำเตือนไปแล้วได้อย่างไร ในลักษณะทั่วไป
  • Adobe Community: การพัฒนา PHP: ทำไมการเปลี่ยนเส้นทางไม่ทำงาน (ส่งส่วนหัวไปแล้ว)
  • คำถามที่พบบ่อยเกี่ยวกับนิวเคลียส: "ส่วนหัวของหน้าถูกส่งไปแล้ว" หมายความว่าอย่างไร
  • หนึ่งในคำอธิบายที่ละเอียดกว่านี้คือHTTP Headers และ PHP header () Function - บทช่วยสอนโดย NicholasSolutions (ลิงก์ Internet Archive) ครอบคลุมรายละเอียด HTTP และให้แนวทางบางประการสำหรับการเขียนสคริปต์ใหม่
203 phihag Nov 07 2011 at 00:44

ข้อความแสดงข้อผิดพลาดนี้จะถูกทริกเกอร์เมื่อมีการส่งสิ่งใด ๆก่อนที่คุณจะส่งส่วนหัว HTTP (มีsetcookieหรือheader) สาเหตุทั่วไปในการส่งออกบางสิ่งก่อนส่วนหัว HTTP คือ:

  • ช่องว่างโดยบังเอิญมักอยู่ที่จุดเริ่มต้นหรือจุดสิ้นสุดของไฟล์เช่นนี้

     <?php
    // Note the space before "<?php"
    ?>
    

       เพื่อหลีกเลี่ยงปัญหานี้เพียงแค่ละทิ้งการปิด?>- ไม่จำเป็นต้องใช้อีกต่อไป

  • ลำดับไบต์ทำเครื่องหมายที่จุดเริ่มต้นของไฟล์ php ตรวจสอบไฟล์ php ของคุณด้วยตัวแก้ไขฐานสิบหกเพื่อดูว่าเป็นเช่นนั้นหรือไม่ 3F 3Cพวกเขาควรจะเริ่มต้นด้วยไบต์ คุณสามารถลบ BOM ได้อย่างปลอดภัยEF BB BFตั้งแต่เริ่มต้นไฟล์
  • การส่งออกอย่างชัดเจนเช่นการโทรไปecho, printf, readfile, passthruรหัสก่อน<?ฯลฯ
  • คำเตือนออกมาโดย php หากdisplay_errorsคุณสมบัติ php.ini ถูกตั้งค่าไว้ แทนที่จะหยุดทำงานด้วยความผิดพลาดของโปรแกรมเมอร์ php จะแก้ไขข้อผิดพลาดและส่งเสียงเตือน ในขณะที่คุณสามารถแก้ไขการกำหนดค่าdisplay_errorsหรือerror_reporting ได้แต่คุณควรแก้ไขปัญหาดังกล่าว
    สาเหตุทั่วไปคือการเข้าถึงองค์ประกอบที่ไม่ได้กำหนดของอาร์เรย์ (เช่น$_POST['input']โดยไม่ใช้emptyหรือissetเพื่อทดสอบว่าอินพุตถูกตั้งค่าไว้หรือไม่) หรือใช้ค่าคงที่ที่ไม่ได้กำหนดแทนสตริงลิเทอรัล (เช่นใน$_POST[input]หมายเหตุเครื่องหมายคำพูดที่ขาดหายไป)

การเปิดบัฟเฟอร์เอาต์พุตควรทำให้ปัญหาหายไป การส่งออกทั้งหมดหลังจากการเรียกร้องให้มีบัฟเฟอร์ในหน่วยความจำจนกว่าคุณจะปล่อยบัฟเฟอร์เช่นกับob_startob_end_flush

อย่างไรก็ตามในขณะที่การบัฟเฟอร์เอาต์พุตหลีกเลี่ยงปัญหาคุณควรพิจารณาว่าเหตุใดแอปพลิเคชันของคุณจึงส่งออกเนื้อหา HTTP ก่อนส่วนหัว HTTP นั่นก็เหมือนกับการรับโทรศัพท์และพูดคุยเกี่ยวกับวันและสภาพอากาศของคุณก่อนที่จะบอกผู้โทรว่าเขาได้รับหมายเลขผิด

126 ManishShrivastava Aug 01 2012 at 13:43

ฉันได้รับข้อผิดพลาดนี้หลายครั้งก่อนหน้านี้และฉันมั่นใจว่าโปรแกรมเมอร์ PHP ทุกคนได้รับข้อผิดพลาดนี้อย่างน้อยหนึ่งครั้งก่อนหน้านี้

แนวทางแก้ไขที่เป็นไปได้ 1

ข้อผิดพลาดนี้อาจเกิดจากช่องว่างก่อนเริ่มไฟล์หรือหลังสิ้นสุดไฟล์ช่องว่างเหล่านี้ไม่ควรอยู่ที่นี่

เช่นไม่ควรมีพื้นที่ว่างที่นี่

   echo "your code here";

?>
THERE SHOULD BE NO BLANK SPACES HERE

ตรวจสอบไฟล์ทั้งหมดที่เกี่ยวข้องกับไฟล์ที่ทำให้เกิดข้อผิดพลาดนี้

หมายเหตุ: บางครั้ง EDITOR (IDE) เช่น gedit (ตัวแก้ไข linux เริ่มต้น) จะเพิ่มบรรทัดว่างหนึ่งบรรทัดในไฟล์บันทึก สิ่งนี้ไม่ควรเกิดขึ้น หากคุณใช้ Linux คุณสามารถใช้ตัวแก้ไข VI เพื่อลบช่องว่าง / บรรทัดหลัง?> ที่ท้ายเพจ

แนวทางที่เป็นไปได้ 2:หากไม่ใช่กรณีของคุณให้ใช้ob_startเพื่อส่งออกบัฟเฟอร์:

<?php
  ob_start();

  // code 

 ob_end_flush();
?> 

การดำเนินการนี้จะเปิดการบัฟเฟอร์เอาต์พุตและส่วนหัวของคุณจะถูกสร้างขึ้นหลังจากที่เพจถูกบัฟเฟอร์

90 IpsitaRout Mar 24 2013 at 19:54

แทนบรรทัดด้านล่าง

//header("Location:".ADMIN_URL."/index.php");

เขียน

echo("<script>location.href = '".ADMIN_URL."/index.php?msg=$msg';</script>");

หรือ

?><script><?php echo("location.href = '".ADMIN_URL."/index.php?msg=$msg';");?></script><?php

มันจะแก้ปัญหาของคุณได้อย่างแน่นอน ฉันประสบปัญหาเดียวกัน แต่ฉันแก้ไขด้วยการเขียนตำแหน่งส่วนหัวด้วยวิธีข้างต้น

41 SethCarnegie Nov 07 2011 at 00:45

คุณทำ

printf ("Hi %s,</br />", $name);

ก่อนตั้งค่าคุกกี้ซึ่งไม่ได้รับอนุญาต คุณไม่สามารถส่งเอาต์พุตก่อนส่วนหัวหรือแม้แต่บรรทัดว่าง

34 T.Todua Apr 10 2015 at 02:22

ปัญหาทั่วไป:

(คัดลอกมาจาก: แหล่งที่มา )

====================

1)ไม่ควรมีเอาต์พุตใด ๆ (เช่นecho..หรือโค้ด HTML) ก่อนheader(.......);คำสั่ง

2)ลบช่องว่าง (หรือขึ้นบรรทัดใหม่ ) ก่อน<?phpและหลัง?>แท็ก

3) กฎทองคำ! - ตรวจสอบว่าไฟล์ php นั้น (และถ้าเป็นincludeไฟล์อื่นของคุณ) มีUTF8 โดยไม่มีการเข้ารหัสBOM (ไม่ใช่แค่UTF-8 ) นั่นเป็นปัญหาในหลาย ๆ กรณี (เนื่องจากไฟล์ที่เข้ารหัสUTF8มีอักขระพิเศษบางอย่างในจุดเริ่มต้นของไฟล์ php ซึ่งโปรแกรมแก้ไขข้อความของคุณไม่แสดง) !!!!!!!!!!!

4)หลังจากที่header(...);คุณต้องใช้exit;

5)ใช้การอ้างอิง 301 หรือ 302 เสมอ:

header("location: http://example.com",  true,  301 );  exit;

6) เปิดการรายงานข้อผิดพลาดและค้นหาข้อผิดพลาด ข้อผิดพลาดของคุณอาจเกิดจากฟังก์ชันที่ไม่ทำงาน เมื่อคุณเปิดการรายงานข้อผิดพลาดคุณควรแก้ไขข้อผิดพลาดสูงสุดก่อนเสมอ ตัวอย่างเช่นอาจเป็น "คำเตือน: date_default_timezone_get (): ไม่ปลอดภัยที่จะพึ่งพาการตั้งค่าเขตเวลาของระบบ" - จากนั้นยิ่งลงไปอีกคุณอาจเห็นข้อผิดพลาด "ไม่ได้ส่งส่วนหัว" หลังจากแก้ไขข้อผิดพลาดสูงสุด (อันดับแรก) แล้วให้โหลดหน้าเว็บของคุณใหม่ หากคุณยังคงมีข้อผิดพลาดให้แก้ไขข้อผิดพลาดสูงสุดอีกครั้ง

7)หากไม่สามารถช่วยได้ให้ใช้การเปลี่ยนเส้นทาง JAVSCRIPT (อย่างไรก็ตามวิธีที่ไม่แนะนำอย่างยิ่ง) อาจเป็นโอกาสสุดท้ายในกรณีที่กำหนดเอง ... :

echo "<script type='text/javascript'>window.top.location='http://website.com/';</script>"; exit;
33 Sarfraz Nov 07 2011 at 00:45

เป็นเพราะบรรทัดนี้:

printf ("Hi %s,</br />", $name);

คุณไม่ควรพิมพ์ / สะท้อนสิ่งใด ๆ ก่อนส่งส่วนหัว

27 Sliq May 17 2012 at 03:37

เคล็ดลับง่ายๆ: ช่องว่างง่ายๆ (หรืออักขระพิเศษที่มองไม่เห็น) ในสคริปต์ของคุณก่อน<?phpแท็กแรกสามารถทำให้เกิดสิ่งนี้ได้! โดยเฉพาะอย่างยิ่งเมื่อคุณทำงานเป็นทีมและมีใครบางคนกำลังใช้ IDE ที่ "อ่อนแอ" หรือยุ่งเกี่ยวกับไฟล์ด้วยโปรแกรมแก้ไขข้อความแปลก ๆ

ฉันได้เห็นสิ่งเหล่านี้แล้ว;)

22 MD.SahibBinMahboob Nov 08 2013 at 08:29

การปฏิบัติที่ไม่ดีอีกประการหนึ่งอาจทำให้เกิดปัญหานี้ซึ่งยังไม่ได้ระบุไว้

ดูข้อมูลโค้ดนี้:

<?php
include('a_important_file.php'); //really really really bad practise
header("Location:A location");
?>

ของก็โอเคใช่มั้ย?

จะเกิดอะไรขึ้นถ้า "a_important_file.php" เป็นดังนี้:

<?php
//some php code 
//another line of php code
//no line above is generating any output
?>

 ----------This is the end of the an_important_file-------------------

นี้จะไม่ทำงาน? เพราะมีการสร้างบรรทัดใหม่แล้ว

ตอนนี้แม้ว่านี่จะไม่ใช่สถานการณ์ทั่วไปถ้าคุณใช้เฟรมเวิร์ก MVC ซึ่งโหลดไฟล์จำนวนมากก่อนที่จะส่งมอบสิ่งต่างๆไปยังคอนโทรลเลอร์ของคุณ? นี่ไม่ใช่สถานการณ์ที่ผิดปกติ เตรียมพร้อมสำหรับเรื่องนี้

จากPSR-2 2.2:


  • ไฟล์ PHP ทั้งหมดต้องใช้ไฟล์Unix LF (linefeed) line ending.
  • ไฟล์ PHP ทั้งหมดต้องลงท้ายด้วยไฟล์single blank line.
  • แท็กปิด?> ต้องมาomittedจากไฟล์ที่มีonly php

เชื่อฉันเถอะว่าการทำตามมาตรฐานนี้สามารถช่วยชีวิตคุณได้หลายชั่วโมง :)

16 Lupin May 22 2015 at 03:39

บางครั้งเมื่อกระบวนการ dev มีทั้งสถานีงาน WIN และระบบ LINUX (โฮสติ้ง) และในโค้ดคุณไม่เห็นผลลัพธ์ใด ๆ ก่อนบรรทัดที่เกี่ยวข้องอาจเป็นการจัดรูปแบบของไฟล์และไม่มีการสิ้นสุดบรรทัดUnix LF (linefeed) .

สิ่งที่เรามักจะทำเพื่อแก้ไขปัญหานี้อย่างรวดเร็วคือการเปลี่ยนชื่อไฟล์และบนระบบ LINUX สร้างไฟล์ใหม่แทนไฟล์ที่เปลี่ยนชื่อจากนั้นคัดลอกเนื้อหาลงในนั้น หลายครั้งการแก้ปัญหานี้เนื่องจากไฟล์บางไฟล์ที่สร้างขึ้นใน WIN เมื่อย้ายไปที่โฮสติ้งทำให้เกิดปัญหานี้

การแก้ไขนี้เป็นการแก้ไขที่ง่ายสำหรับไซต์ที่เราจัดการโดย FTP และบางครั้งอาจช่วยสมาชิกทีมใหม่ของเราได้บ้าง

3 BiswadeepSarkar Feb 03 2015 at 11:50

โดยทั่วไปข้อผิดพลาดนี้จะเกิดขึ้นเมื่อเราส่งส่วนหัวหลังจากสะท้อนหรือพิมพ์ start_session()หากข้อผิดพลาดนี้เกิดขึ้นบนหน้าเว็บที่เฉพาะเจาะจงแล้วให้แน่ใจว่าหน้าไม่ได้สะท้อนอะไรก่อนที่โทรไป

ตัวอย่างข้อผิดพลาดที่คาดเดาไม่ได้:

 <?php //a white-space before <?php also send for output and arise error
session_start();
session_regenerate_id();

//your page content

อีกหนึ่งตัวอย่าง:

<?php
includes 'functions.php';
?> <!-- This new line will also arise error -->
<?php
session_start();
session_regenerate_id();

//your page content

สรุป: อย่าส่งออกอักขระใด ๆ ก่อนที่จะเรียกsession_start()หรือheader()ฟังก์ชันที่ไม่เว้นแม้แต่ช่องว่างหรือบรรทัดใหม่