Pertanyaan Cara memperbaiki "Header sudah dikirim" kesalahan dalam PHP


Saat menjalankan skrip saya, saya mendapatkan beberapa kesalahan seperti ini:

Peringatan: Tidak dapat mengubah informasi header - header sudah dikirim oleh (output dimulai pada /some/file.php:12) di /some/file.php di garis 23

Garis-garis yang disebutkan dalam pesan kesalahan mengandung header() dan setcookie() panggilan.

Apa alasannya untuk ini? Dan bagaimana cara memperbaikinya?


836
2017-11-06 17:45


asal


Jawaban:


Tidak ada output sebelum mengirim header!

Fungsi yang mengirim / memodifikasi tajuk HTTP harus dipanggil sebelum hasil apapun dibuat. ringkasan ⇊ Kalau tidak, panggilan gagal:

Peringatan: Tidak dapat mengubah informasi header - header sudah dikirim (output dimulai pada skrip: garis)

Beberapa fungsi yang memodifikasi tajuk HTTP adalah:

Output dapat berupa:

  • Tak disengaja:

    • Spasi kosong sebelumnya <?php atau setelah ?>
    • Itu UTF-8 Byte Order Mark secara khusus
    • Pesan kesalahan atau pemberitahuan sebelumnya
  • Disengaja:

    • print, echo dan fungsi lain yang menghasilkan output
    • Mentah <html> bagian sebelumnya <?php kode.

Kenapa itu terjadi?

Untuk memahami mengapa header harus dikirim sebelum dikeluarkan, itu perlu untuk melihat yang khas HTTP tanggapan. Skrip PHP terutama menghasilkan konten HTML, tetapi juga melewatkan a set header HTTP / CGI ke server web:

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>

Halaman / output selalu mengikuti header. PHP harus lulus header ke server web terlebih dahulu. Itu hanya bisa melakukannya sekali. Setelah double-linebreak itu tidak pernah bisa mengamandemennya.

Ketika PHP menerima hasil pertama (print, echo, <html>) itu akan menyiram semua tajuk yang dikumpulkan. Setelah itu dapat mengirim semua output yang diinginkannya. Tetapi mengirim header HTTP lebih lanjut adalah mustahil.

Bagaimana Anda bisa mengetahui di mana output prematur terjadi?

Itu header() peringatan berisi semua informasi yang relevan untuk cari penyebab masalah:

Peringatan: Tidak dapat mengubah informasi header - header sudah dikirim oleh    (output dimulai pada / www / usr2345 / htdocs /auth.php: 52) di   /www/usr2345/htdocs/index.php pada baris 100

Di sini "garis 100" mengacu pada skrip dimana header()  doa gagal.

"output dimulai pada"Catatan dalam kurung lebih signifikan. Itu denominasikan sumber output sebelumnya. Dalam contoh ini auth.php dan garis 52. Di situlah Anda harus mencari keluaran prematur.

Penyebab umum:

  1. Cetak, gema

    Output yang disengaja dari print dan echo pernyataan akan berakhir kesempatan untuk mengirim header HTTP. Aliran aplikasi harus direstrukturisasi untuk menghindari itu. Menggunakan fungsi dan skema templating. Memastikan header() panggilan terjadi sebelum pesan ditulis.

    Fungsi yang menghasilkan output termasuk

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


     antara lain dan fungsi yang ditentukan pengguna.

  2. Area HTML mentah

    Bagian HTML yang tidak dipetakan dalam a .php file adalah output langsung juga. Kondisi skrip yang akan memicu a header() panggilan harus diperhatikan sebelum apa saja mentah <html> blok.

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

    Gunakan skema templating untuk memisahkan pemrosesan dari logika output.

    • Tempatkan kode pemrosesan formulir di skrip.
    • Gunakan variabel string sementara untuk menunda pesan.
    • Logika output aktual dan output HTML yang dicampur harus mengikuti yang terakhir.

  3. Spasi kosong sebelumnya <?php untuk "script.php baris 1"peringatan

    Jika peringatan mengacu pada output sejalan 1, itu sebagian besar terkemuka ruang putih, teks atau HTML sebelum pembukaan <?php token.

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

    Demikian pula hal itu dapat terjadi untuk skrip tambahan atau bagian skrip:

    ?>
    
    <?php
    

    PHP sebenarnya memakan sebuah tunggal linebreak setelah tag dekat. Tetapi itu tidak akan terjadi mengimbangi beberapa baris baru atau tab atau spasi bergeser ke celah tersebut.

  4. UTF-8 BOM

    Linebreak dan spasi saja bisa menjadi masalah. Tetapi ada juga yang "tidak terlihat" urutan karakter yang dapat menyebabkan ini. Paling terkenal UTF-8 BOM (Byte-Order-Mark) yang tidak ditampilkan oleh sebagian besar editor teks. Ini urutan byte EF BB BF, yang mana bersifat opsional dan berlebihan untuk dokumen berenkode UTF-8. Namun PHP harus memperlakukan sebagai hasil mentah. Ini mungkin muncul sebagai karakter  dalam output (jika klien menafsirkan dokumen sebagai Latin-1) atau "sampah" serupa.

    Khususnya editor grafis dan IDE berbasis Java tidak mengindahkannya kehadiran. Mereka tidak memvisualisasikannya (diwajibkan oleh standar Unicode). Kebanyakan programmer dan editor konsol melakukan:

    joes editor showing UTF-8 BOM placeholder, and MC editor a dot

    Di sana mudah untuk mengenali masalah sejak dini. Editor lain dapat mengidentifikasi kehadirannya dalam menu file / pengaturan (Notepad ++ pada Windows dapat mengidentifikasi dan memperbaiki masalah), Pilihan lain untuk memeriksa keberadaan BOM adalah beralih ke suatu hexeditor. Pada sistem * nix hexdump biasanya tersedia, jika bukan varian grafis yang menyederhanakan pengauditan masalah ini dan lainnya:

    beav hexeditor showing utf-8 bom

    Perbaikan yang mudah adalah dengan mengatur editor teks untuk menyimpan file sebagai "UTF-8 (no BOM)" atau nomenklatur semacam itu. Seringkali pendatang baru berusaha untuk menciptakan yang baru file dan salin & tempelkan kode sebelumnya kembali.

    Utilitas koreksi

    Ada juga alat otomatis untuk memeriksa dan menulis ulang file teks (sed/awk atau recode). Untuk PHP khusus ada phptags beri tidier. Ini menulis ulang dekat dan membuka tag ke dalam bentuk panjang dan pendek, tetapi juga mudah perbaikan yang memimpin dan membuntuti spasi, Unicode dan UTF-x BOM masalah:

    phptags  --whitespace  *.php
    

    Ini masuk akal untuk digunakan secara keseluruhan termasuk atau direktori proyek.

  5. Spasi setelah ?>

    Jika sumber kesalahan disebutkan sebagai di belakang penutupan ?> maka di sinilah beberapa spasi atau teks mentah ditulis. Penanda akhir PHP tidak mengakhiri eksekusi skrip pada ini titik. Karakter teks / spasi apa pun setelah itu akan ditulis sebagai konten halaman masih.

    Biasanya disarankan, khususnya untuk pendatang baru, yang tertinggal ?> PHP tag dekat harus dihilangkan. Ini berhentilah sebagian kecil dari kasus-kasus ini. (Cukup umum include()d skrip adalah pelakunya.)

  6. Sumber kesalahan disebutkan sebagai "Tidak dikenal di baris 0"

    Ini biasanya pengaturan ekstensi PHP atau php.ini jika tidak ada sumber kesalahan dikonkretkan.

    • Kadang-kadang itu gzip pengaturan encoding aliran atau ob_gzhandler.
    • Tapi itu juga bisa dimuat dua kali lipat extension= modul menghasilkan pesan startup / peringatan PHP implisit.

  7. Pesan kesalahan sebelumnya

    Jika pernyataan atau ekspresi PHP lainnya menyebabkan pesan peringatan atau pemberitahuan yang dicetak, yang juga dianggap sebagai output prematur.

    Dalam hal ini Anda perlu menghindari kesalahan, menunda eksekusi pernyataan, atau menekan pesan dengan mis. isset() atau @() - ketika tidak menghalangi debug nanti.

Tidak ada pesan kesalahan

Jika Anda memiliki error_reporting atau display_errors dinonaktifkan per php.ini, maka tidak ada peringatan yang akan muncul. Tetapi mengabaikan kesalahan tidak akan membuat masalah pergi jauh. Header masih tidak dapat dikirim setelah keluaran prematur.

Jadi ketika header("Location: ...") redirect diam-diam gagal itu sangat disarankan untuk menyelidiki peringatan. Aktifkan kembali dengan dua perintah sederhana di atas skrip pemanggilan:

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

Atau set_error_handler("var_dump"); jika semuanya gagal.

Berbicara tentang header pengalihan, Anda harus sering menggunakan idiom ini untuk jalur kode terakhir:

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

Lebih disukai bahkan fungsi utilitas, yang mencetak pesan pengguna dalam kasus header() kegagalan.

Output buffering sebagai solusi

PHP penyangga keluaran adalah solusi untuk mengatasi masalah ini. Sering berfungsi dengan baik, tetapi tidak seharusnya menggantikan penataan aplikasi yang benar dan memisahkan output dari kontrol logika. Tujuan sebenarnya adalah meminimalkan transfer chunk ke server web.

  1. Itu output_buffering= pengaturan tetap dapat membantu. Konfigurasikan di php.ini atau via .htaccess atau bahkan .user.ini di pengaturan FPM / FastCGI modern.
    Mengaktifkannya akan memungkinkan PHP untuk menyangga keluaran alih-alih meneruskannya ke server web segera. PHP dengan demikian dapat mengumpulkan header HTTP.

  2. Itu juga bisa dilibatkan dengan panggilan ke ob_start(); di atas skrip permohonan. Namun yang kurang dapat diandalkan untuk beberapa alasan:

    • Bahkan jika <?php ob_start(); ?> memulai skrip pertama, spasi putih atau BOM mungkin dikocok sebelumnya, menjadikannya tidak efektif.

    • Ini dapat menyembunyikan spasi untuk output HTML. Tetapi segera setelah aplikasi logika mencoba mengirim konten biner (gambar yang dihasilkan misalnya), output asing yang disangga menjadi masalah. (Memenuhi ob_clean() sebagai solusi lebih jelas.)

    • Buffer terbatas dalam ukuran, dan dapat dengan mudah dibanjiri ketika dibiarkan ke default. Dan itu bukan kejadian langka, sulit untuk dilacak ketika itu terjadi.

Kedua pendekatan itu mungkin menjadi tidak dapat diandalkan - khususnya ketika beralih di antara keduanya setup pengembangan dan / atau server produksi. Itulah mengapa buffering output secara luas dianggap hanya kruk / ketat solusi.

Lihat juga contoh penggunaan dasar di manual, dan untuk lebih pro dan kontra:

Tapi itu berhasil di server lain !?

Jika Anda tidak mendapatkan peringatan header sebelumnya, maka penyangga keluaran  pengaturan php.ini  telah berubah. Ini mungkin tidak terkonfigurasi di server saat ini / baru.

Memeriksa dengan headers_sent()

Anda selalu dapat menggunakan headers_sent() untuk menyelidiki jika masih mungkin untuk ... mengirim header. Yang berguna untuk mencetak secara bersyarat sebuah info atau menerapkan logika fallback lainnya.

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

Pemecahan masalah yang diperlukan adalah:

  • HTML <meta> menandai

    Jika aplikasi Anda secara struktural sulit diperbaiki, maka mudah (tapi agak tidak profesional) cara untuk mengizinkan pengalihan adalah menyuntikkan HTML <meta> menandai. Pengalihan dapat dicapai dengan:

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

    Atau dengan penundaan singkat:

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

    Ini mengarah ke HTML yang tidak valid ketika digunakan melewati <head> bagian. Sebagian besar browser masih menerimanya.

  • Pengalihan JavaScript

    Sebagai alternatif a Pengalihan JavaScript dapat digunakan untuk pengalihan halaman:

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

    Meskipun ini sering lebih sesuai dengan HTML daripada <meta> solusi, itu menimbulkan ketergantungan pada klien yang mampu JavaScript.

Namun kedua pendekatan memberikan fallback yang dapat diterima ketika header HTTP asli () panggilan gagal. Idealnya, Anda selalu menggabungkan ini dengan pesan yang ramah pengguna dan tautan yang dapat diklik sebagai pilihan terakhir. (Yang misalnya adalah apa yang http_redirect () Ekstensi PECL tidak.)

Mengapa setcookie() dan session_start() juga terpengaruh

Kedua setcookie() dan session_start() perlu mengirim Set-Cookie: Header HTTP. Kondisi yang sama berlaku, dan pesan kesalahan yang serupa akan dihasilkan untuk situasi output yang prematur.

(Tentu saja mereka juga dipengaruhi oleh cookie yang dinonaktifkan di browser, atau bahkan masalah proxy. Fungsionalitas sesi jelas juga tergantung pada gratis ruang disk dan pengaturan php.ini lainnya, dll.)

Tautan lebih lanjut


2639
2017-11-06 17:44



Pesan kesalahan ini dipicu saat apa pun dikirim sebelum Anda mengirim tajuk HTTP (dengan setcookie atau header). Alasan umum untuk mengeluarkan sesuatu sebelum header HTTP adalah:

  • Ruang kosong tidak disengaja, sering di awal atau akhir file, seperti ini:

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

Untuk menghindarinya, tinggalkan saja penutupnya ?> - itu tidak diperlukan.

  • Tanda pesanan Byte di awal file php. Periksa file php Anda dengan hex editor untuk mengetahui apakah itu yang terjadi. Mereka harus mulai dengan byte 3F 3C. Anda dapat menghapus BOM dengan aman EF BB BF dari awal file.
  • Output eksplisit, seperti panggilan ke echo, printf, readfile, passthru, kode sebelumnya <? dll.
  • Peringatan dikeluarkan oleh php, jika display_errors properti php.ini diatur. Alih-alih menabrak kesalahan programmer, php diam-diam memperbaiki kesalahan dan memancarkan peringatan. Meskipun Anda dapat memodifikasi display_errors atau error_reporting konfigurasi, Anda sebaiknya memperbaiki masalah.
    Alasan umum adalah akses ke elemen array yang tidak terdefinisi (seperti $_POST['input'] tanpa menggunakan empty atau isset untuk menguji apakah input ditetapkan), atau menggunakan konstanta yang tidak terdefinisi, bukan string literal (seperti pada $_POST[input], perhatikan tanda kutip yang hilang).

Menyalakan penyangga keluaran harus membuat masalah pergi; semua output setelah panggilan ke ob_start disangga dalam memori hingga Anda melepaskan buffer, mis. dengan ob_end_flush.

Namun, sementara buffering keluaran menghindari masalah, Anda harus benar-benar menentukan mengapa aplikasi Anda menghasilkan sebuah badan HTTP sebelum header HTTP. Itu seperti menerima panggilan telepon dan mendiskusikan hari Anda dan cuaca sebelum memberi tahu si penelepon bahwa dia salah nomor.


178
2017-08-01 06:43



Saya mendapatkan kesalahan ini berkali-kali sebelumnya. Dan saya yakin semua programmer PHP setidaknya sekali mendapatkan kesalahan ini. Untuk mengatasi kesalahan ini Anda dapat memecahkan solusi penggunaan sesuai tingkat masalah Anda:

Kemungkinan Solusi 1:

Anda mungkin telah meninggalkan ruang kosong sebelum atau setelah (di akhir file setelah?>) yaitu

THERE SHOULD BE NO BLANK SPACES HERE
<?php  

   echo "your code here";

?>
DO CHECK FOR BLANK SPACES HERE AS WELL; THIS LINE (blank line) SHOULD NOT EXIST.

Sebagian besar waktu ini harus menyelesaikan masalah Anda. Jangan periksa semua file yang terkait dengan file Anda require.

catatan:  Kadang-kadang EDITOR (IDE) seperti gedit (editor linux default) menambahkan satu baris kosong pada save save file. Ini seharusnya tidak terjadi. Jika Anda menggunakan linux. Anda dapat menggunakan editor VI untuk menghapus spasi / baris setelah?> di akhir halaman.

Jika ini bukan kasus Anda, maka Anda bisa menggunakannya ob_start untuk penyangga keluaran seperti di bawah ini:

Kemungkinan Solusi 2:

<?php
  ob_start();

  // code 

 ob_end_flush();
?> 

101
2018-03-24 12:54



Alih-alih garis bawah

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

menulis

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

atau

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

Itu pasti akan menyelesaikan masalahmu. Saya menghadapi masalah yang sama tetapi saya berhasil memecahkannya dengan menulis lokasi tajuk dengan cara di atas.


73
2017-11-06 17:45



Anda melakukannya

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

sebelum menyetel cookie, yang tidak diizinkan. Anda tidak dapat mengirim output apa pun sebelum header, bahkan tidak ada baris kosong.


38
2017-11-06 17:45



Itu karena garis ini:

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

Anda tidak harus cetak / gema apa pun sebelum mengirim header.


29
2018-05-16 20:37



Tip sederhana: Ruang sederhana (atau char khusus tak terlihat) dalam naskah Anda, tepat sebelum yang pertama <?php tag, dapat menyebabkan ini! Terutama ketika Anda bekerja dalam tim dan seseorang menggunakan IDE "lemah" atau telah mengacaukan file dengan editor teks aneh.

Saya telah melihat hal-hal ini;)


25
2017-11-08 01:29