Cara untuk Membetulkan Ralat "Tajuk Sudah Dihantar" dalam PHP
P粉210405394
P粉210405394 2023-10-09 21:06:28
0
2
562

Apabila menjalankan skrip saya, saya mendapat beberapa ralat seperti ini:

Amaran: Tidak dapat mengubah suai maklumat pengepala - pengepala sudah dihantar oleh /some/file.php (Output bermula pada /some/file.php:12)

Barisan yang disebut dalam mesej ralat mengandungi panggilan header()setcookie().

Apakah sebabnya? Bagaimana untuk menyelesaikannya?

P粉210405394
P粉210405394

membalas semua(2)
P粉071602406

Hantar apa-apa sahaja sebelum menghantar pengepala HTTP (gunakan setcookieheader). Sebab biasa untuk mengeluarkan sesuatu sebelum pengepala HTTP ialah:

  • Ruang yang tidak dijangka, biasanya pada permulaan atau penghujung fail, seperti ini:

           Untuk mengelakkan perkara ini, tinggalkan sahaja pengakhiran ?> - ia tidak diperlukan lagi.

untuk menguji sama ada input ditetapkan), Atau gunakan pemalar yang tidak ditentukan dan bukannya literal rentetan (seperti dalam $_POST[input], perhatikan petikan yang tiada).

Hidupkan output bufferingob_start 后的所有输出都缓冲在内存中,直到您释放缓冲区,例如与 ob_end_flush sepatutnya melakukan helah; semua output selepas memanggil ob_start

ditimbal dalam memori sehingga anda melepaskan penimbal, mis /ob_end_flush" rel="nofollow noreferrer">ob_end_flush

.

🎜Walau bagaimanapun, sementara penimbalan output boleh mengelakkan masalah ini, anda harus benar-benar menentukan sebab aplikasi anda mengeluarkan badan HTTP sebelum pengepala HTTP. Ia seperti menjawab telefon dan membincangkan hari anda dan cuaca, kemudian memberitahu pemanggil bahawa dia mendail nombor yang salah. 🎜
P粉087951442

Tiada output sebelum menghantar tajuk!

Sebelum sebarang output boleh dilakukan, fungsi yang menghantar/mengubah suai pengepala HTTP mesti dipanggil. Ringkasan⇊ Jika tidak, panggilan gagal:

Beberapa fungsi yang mengubah suai pengepala HTTP ialah:

Output boleh:

  • Tidak disengajakan:

  • Sengaja:

    • printecho dan fungsi lain yang menghasilkan output
    • 代码之前的原始 bahagian.

Mengapa ini berlaku?

Adalah perlu untuk memahami mengapa pengepala mesti dihantar sebelum mengeluarkan Lihat tipikal HTTP balas. Skrip PHP terutamanya menjana kandungan HTML dan juga lulus a Set pengepala HTTP/CGI yang dihantar ke pelayan web:

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

PHP page output page

Content

Some more output follows...

and

Halaman/Output sentiasa mengikut tajuk. PHP mesti lulus Mula-mula pengepala dihantar ke pelayan web. Ia hanya boleh melakukan ini sekali sahaja. Mereka tidak lagi boleh diubah suai selepas dua bungkus.

Apabila PHP menerima output pertama (printecho, ), ia akan Segarkan semulasemua pengepala yang dikumpul. Selepas itu ia boleh menghantar semua output Ia mahu. Tetapi menghantar pengepala HTTP selanjutnya tidak boleh dilakukan.

Bagaimana untuk mengetahui di mana pengeluaran pramatang berlaku?

header() Amaran mengandungi semua maklumat yang berkaitan Punca masalah kedudukan:

Di sini "baris 100" merujuk kepada skrip yang header() memanggil dan gagal.

Komen "output bermula pada " di dalam kurungan adalah lebih penting. Ia mewakili sumber keluaran sebelumnya. Dalam contoh ini ialah auth.php dan baris ke 52. Di sinilah anda perlu mencari keluaran pramatang.

Sebab biasa:

  1. Cetak dan bergema

    Output yang disengajakan bagi pernyataan

    printecho akan menamatkan peluang untuk menghantar pengepala HTTP. Proses permohonan mesti disusun semula untuk mengelakkan situasi ini. Menggunakan fungsi dan penyelesaian templat. Pastikan panggilan header() berlaku sebelum mesej Semuanya sudah tertulis.

    Fungsi yang menghasilkan output termasuk

    • 打印echoprintfvprintf
    • trigger_errorob_flushob_end_flushvar_dumpprint_r
    • readfilepassthruflushimagepngimagejpeg


    Dan fungsi lain dan ditakrifkan pengguna.

  2. Kawasan HTML asal

    Bahagian HTML yang tidak dihuraikan dalam fail .php juga dikeluarkan secara langsung. Seseorang mesti memberi perhatian kepada syarat skrip yang akan mencetuskan panggilan header() Sebelum sebarang original blok.

    
    

    Gunakan skema templat untuk memisahkan pemprosesan daripada logik output.

    • Letakkan kod pengendalian borang di atas skrip.
    • Gunakan pembolehubah rentetan sementara untuk menangguhkan mesej.
    • Logik output sebenar dan output HTML campuran hendaklah yang terakhir.

  3. Ruang sebelum itu bermaksud "skrip.php Baris 1" amaran

    Jika amaran merujuk kepada output sebaris1, maka terutamanya Memimpin ruang sebelum pembukaan tag, teks atau HTML.

    
    

    Begitu juga ini boleh berlaku dengan skrip tambahan atau bahagian skrip:

    ?>
    
    
    

    PHP sebenarnya mengambil single line break selepas menutup tag. tetapi ia tidak akan Mengimbangi berbilang baris baharu, tab atau ruang yang dialihkan ke dalam jurang tersebut.

  4. UTF-8 BOM

    Barisan baharu dan ruang sahaja boleh menjadi masalah. Tetapi ada juga yang "tidak kelihatan" Urutan watak yang boleh menyebabkan ini. Yang paling terkenal ialah UTF-8 BOM (Tanda Pesanan Bait) Kebanyakan penyunting teks tidak memaparkannya. Ia adalah urutan bait EF BB BF,对于 UTF-8 编码的文档来说,它是可选且冗余的。然而 PHP 必须将其视为原始输出。它可能在输出中显示为字符  (jika pelanggan mentafsir dokumen sebagai Latin-1) atau "sampah" yang serupa.

    Terutama penyunting grafik dan IDE berasaskan Java tidak menyedarinya Hadir. Mereka tidak menggambarkannya (seperti yang dikehendaki oleh standard Unicode). Walau bagaimanapun, kebanyakan pengaturcara dan editor konsol akan:

    Ini memudahkan untuk mengesan masalah lebih awal. Editor lain mungkin mengenali Ia hadir dalam menu Fail/Tetapan (Notepad++ pada Windows mengenali dan Selesai Masalah), Pilihan lain untuk menyemak kewujudan BOM ialah menggunakan Hex Editor. Pada sistem *nix hexdump biasanya tersedia, Jika tidak mudah menyemak variasi grafik soalan ini dan soalan lain:

    Penyelesaian mudah ialah menetapkan editor teks anda untuk menyimpan fail sebagai "UTF-8 (tiada BOM)" Atau tatanama yang serupa. Selalunya pemula akan mengambil jalan keluar untuk mencipta fail baharu dan kemudian menyalin dan menampal semula kod sebelumnya.

    Utiliti Pembetulan

    Terdapat juga alatan automatik untuk menyemak dan menulis semula fail teks (sed/awksed/awk代码>重新编码 atau recode). Untuk PHP, khususnya tag phptags lebih kemas. Ia menulis semula tag penutup dan pembukaan ke dalam bentuk panjang dan pendek dan juga mudah Isu ruang hadapan dan belakang, Unicode dan UTF-x BOM:

    phptags  --whitespace  *.php

    Selamat digunakan pada keseluruhan termasuk atau direktori projek.

  5. 后有空格?>

    Jika sumber ralat disebut kemudian Tutup ?> Di sinilah beberapa teks kosong atau mentah ditulis. Teg penutup PHP tidak menamatkan pelaksanaan skrip pada masa ini. Sebarang aksara teks/ruang selepas itu akan ditulis sebagai kandungan halaman masih.

    Secara umumnya disyorkan, terutamanya untuk pemula, untuk mengikuti ?> PHP Teg penutup hendaklah ditinggalkan. Ini mengelakkan sebahagian kecil daripada kes ini. (Skrip include()d yang sangat biasa adalah puncanya.)

  6. Punca ralat dipanggil "Barisan tidak diketahui 0"

    Jika tiada sumber ralat, ia biasanya sambungan PHP atau tetapan php.ini konkrit.

    • Kadangkala gzip Tetapan pengekodan strim atau ob_gzhandler.
    • Tetapi ia juga boleh menjadi mana-mana modul dwi-muat extension= Hasilkan mesej permulaan/amaran PHP tersirat.

  7. Mesej ralat sebelumnya

    Jika pernyataan atau ungkapan PHP lain menyebabkan mesej amaran atau Nota dicetak, yang juga dikira sebagai output pramatang.

    Dalam kes ini, anda perlu mengelakkan kesilapan, Tangguhkan pelaksanaan kenyataan, atau sekat mesej menggunakan cth. isset()isset()@() atau @() - Apabila salah satu tidak menghalang penyahpepijatan kemudian.

Tiada mesej ralat

Jika anda berdasarkan php.ini 禁用了 error_reportingdisplay_errors, Kemudian tiada amaran akan muncul. Tetapi mengabaikan ralat tidak menyelesaikan masalah pergi. Masih tidak dapat menghantar pengepala selepas output pramatang.

Jadi apabila header("Location: ...") ubah hala gagal secara senyap, ia sangat serius Amaran siasatan adalah disyorkan. Dayakan semula mereka dengan dua arahan mudah Di atas skrip panggilan:

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

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

Bercakap tentang pengepala ubah hala, anda harus sentiasa menggunakan simpulan bahasa seperti ini Ini ialah laluan kod terakhir:

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

Adalah yang terbaik untuk menjadi fungsi praktikal yang mencetak mesej pengguna Jika header() gagal.

Penimbalan output sebagai penyelesaian

PHP Penimbalan Output adalah penyelesaian untuk mengurangkan masalah ini. Ia biasanya berfungsi dengan pasti, tetapi tidak sepatutnya Gantikan struktur aplikasi yang betul dan keluarkan berasingan daripada kawalan logik. Tujuan sebenarnya adalah untuk meminimumkan pemindahan chunked ke pelayan web.

  1. output_buffering= Namun, tetapan membantu. Konfigurasikannya dalam php.ini Atau melalui .htaccess Malah .user.ini Persediaan FPM/FastCGI moden.
    Mendayakan ini akan membolehkan PHP menimbal output dan bukannya menghantarnya ke pelayan web dengan segera. Oleh itu, PHP boleh mengagregat pengepala HTTP.

  2. Ia juga boleh dipanggil dengan menelefon ob_start(); di atas skrip panggilan. Walau bagaimanapun, ia tidak begitu boleh dipercayai atas beberapa sebab:

    • Walaupun memulakan skrip pertama, ruang atau BOM mungkin terbatal dan tidak sah sebelum render.

    • Ia boleh menyembunyikan ruang kosong output HTML. Walau bagaimanapun, sebaik sahaja logik aplikasi cuba menghantar kandungan binari (seperti imej yang dijana), Keluaran luar yang ditimbal menjadi masalah. (memerlukan ob_clean()) sebagai penyelesaian selanjutnya. )

    • Saiz penimbal adalah terhad dan mudah melimpah jika dibiarkan pada nilai lalai. Keadaan ini bukan perkara biasa, sukar untuk dikesan一个> apabila ia berlaku.

Oleh itu, kedua-dua kaedah boleh menjadi tidak boleh dipercayai - terutamanya apabila bertukar antara keduanya Persediaan pembangunan dan/atau pelayan pengeluaran. Inilah sebabnya mengapa penimbalan output adalah Secara meluas dianggap sebagai tongkat/penyelesaian yang ketat.

Lihat juga Contoh penggunaan asas Dalam manual, dan lebih banyak kebaikan dan keburukan:

Tetapi ia berfungsi pada pelayan lain! ?

Jika anda tidak mendapat amaran pengepala sebelum ini, penimbalan output tetapan php.ini sudah berubah. Ia mungkin tidak dikonfigurasikan pada pelayan semasa/baharu.

Gunakan headers_sent()检查

Anda sentiasa boleh menggunakan headers_sent() untuk mengesan jika Masih boleh... untuk menghantar pengepala. Ini berguna untuk pencetakan bersyarat maklumat atau gunakan logik sandaran lain.

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

Penyelesaian sandaran yang berguna ialah:

  • HTML tag

    Jika aplikasi anda secara struktur sukar untuk diperbaiki, maka yang mudah (tetapi Agak tidak profesional) Cara untuk membenarkan pengalihan adalah dengan menyuntik HTML Tag. Pengalihan boleh dicapai melalui:

    Atau kelewatan singkat:

    Ini mengakibatkan HTML tidak sah apabila digunakan di luar bahagian . Kebanyakan pelayar masih menerimanya.

  • JavaScript Redirect

    Sebagai alternatif, JavaScript ubah hala Tersedia untuk ubah hala halaman:

    sssccc

    Walaupun ini biasanya lebih mematuhi HTML daripada penyelesaian , Ia mengakibatkan pergantungan pada klien yang didayakan JavaScript.

Walau bagaimanapun, kedua-dua kaedah menghasilkan sandaran yang boleh diterima apabila pengepala HTTP sebenar() Panggilan gagal. Sebaik-baiknya, anda sentiasa menggabungkan ini dengan mesej mesra pengguna, Pautan boleh klik sebagai pilihan terakhir. (Sebagai contoh, http_redirect() Sambungan PECL tidak. )

Kenapasetcookie()session_start()juga terjejas

setcookie()session_start() 都需要发送 Set-Cookie: Pengepala HTTP. Oleh itu, syarat yang sama dikenakan dan mesej ralat yang serupa akan dihasilkan Digunakan dalam kes pengeluaran pramatang.

(Sudah tentu, mereka juga dipengaruhi oleh melumpuhkan kuki dalam penyemak imbas anda Malah isu agensi. Ciri sesi jelas juga bergantung pada percuma Ruang cakera dan tetapan php.ini lain, dsb.)

Lagi pautan

Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan