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 panggilanheader()
和setcookie()
.
Apakah sebabnya? Bagaimana untuk menyelesaikannya?
Hantar apa-apa sahaja sebelum menghantar pengepala HTTP (gunakan
setcookie
或header
). 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.Tanda pesanan- baitterletak pada permulaan fail PHP. Semak fail php anda menggunakan editor hex untuk melihat sama ada ini berlaku. Ia sepatutnya dalam bait
- Keluaran eksplisit, seperti memanggil
- Amaran dikeluarkan oleh php jika sifat
display_errors
atauerror_reporting
atau
untuk menguji sama ada input ditetapkan), Atau gunakan pemalar yang tidak ditentukan dan bukannya literal rentetan (seperti dalam3F 3C
开头。您可以安全地从文件开头删除 BOMEF BB BF
.echo
、printf
、readfile
、passthru
、之前的代码>
dll.display_errors
display_errors
php.ini属性已设置。 php 不会因程序员错误而崩溃,而是默默地修复错误并发出警告。虽然您可以修改display_errors
php.ini ditetapkan. Daripada ranap kerana ralat pengaturcara, php membetulkan ralat secara senyap dan mengeluarkan amaran. Walaupun anda boleh mengubah suai konfigurasidan anda harus menyelesaikan isu tersebut.
$_POST['input']
而不使用empty
或isset
进行测试是否设置了输入),或者使用未定义的常量而不是字符串文字(如$_POST[input]
Sebab biasa ialah mengakses elemen yang tidak ditentukan dalam tatasusunan (cth.$_POST['input']
tanpa menggunakankosong
isset
$_POST[input]
, perhatikan petikan yang tiada).Hidupkanoutput buffering
ditimbal dalam memori sehingga anda melepaskan penimbal, mis /ob_end_flush" rel="nofollow noreferrer">ob_start
后的所有输出都缓冲在内存中,直到您释放缓冲区,例如与ob_end_flush
sepatutnya melakukan helah; semua output selepas memanggilob_start
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.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:
标题
header_remove
/header_remove
session_start
session_regenerate_id
/session_regenerate_id
setcookie
setrawcookie
/setrawcookie
Output boleh:
Tidak disengajakan:
Ruang selepas
- SpesifikUTF-8 Byte Mark Order
- Mesej ralat atau pemberitahuan sebelumnya
之前或
?>
Sengaja:
print
、echo
dan fungsi lain yang menghasilkan output代码之前的原始
bahagian.
Mengapa ini berlaku?
Adalah perlu untuk memahami mengapa pengepala mesti dihantar sebelum mengeluarkan Lihat tipikalHTTPbalas. Skrip PHP terutamanya menjana kandungan HTML dan juga lulus a Set pengepala HTTP/CGI yang dihantar ke pelayan web:
Halaman/Output sentiasamengikuttajuk. 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 (
print
、echo
、,
), ia akanSegarkan 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()
memanggildan gagal.Komen "output bermula pada" di dalam kurungan adalah lebih penting. Ia mewakili sumber keluaran sebelumnya. Dalam contoh ini ialah
auth.php
danbaris ke52
. Di sinilah anda perlu mencari keluaran pramatang.Sebab biasa:
Cetak dan bergema
Output yang disengajakan bagi pernyataanprint
和echo
akan menamatkan peluang untuk menghantar pengepala HTTP. Proses permohonan mesti disusun semula untuk mengelakkan situasi ini. Menggunakan fungsidan penyelesaian templat. Pastikan panggilanheader()
berlaku sebelum mesejSemuanya sudah tertulis.Fungsi yang menghasilkan output termasuk
打印
、echo
、printf
、vprintf
trigger_error
、ob_flush
、ob_end_flush
、var_dump
、print_r
readfile
、passthru
、flush
、imagepng
、imagejpeg
Dan fungsi lain dan ditakrifkan pengguna.
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()
Sebelumsebarangoriginalblok.
Ruang sebelum itu bermaksud "skrip.phpBaris 1" amaran
Jika amaran merujuk kepada output sebaris
1
, maka terutamanya Memimpinruangsebelum pembukaantag, teks atau HTML.
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 ialahUTF-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 danSelesai Masalah), Pilihan lain untuk menyemak kewujudan BOM ialah menggunakanHex 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
/awk
sed
/awk代码>
或重新编码
ataurecode
). Untuk PHP, khususnya tagphptags
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:Selamat digunakan pada keseluruhan termasuk atau direktori projek.
后有空格?>
Jika sumber ralat disebut kemudianTutup
?>
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. Inimengelakkansebahagian kecil daripada kes ini. (Skripinclude()d
yang sangat biasa adalah puncanya.)Punca ralat dipanggil "Barisan tidak diketahui 0"
Jika tiada sumber ralat, ia biasanya sambungan PHP atau tetapan php.ini konkrit.
gzip
Tetapan pengekodan strimatauob_gzhandler
.extension=
Hasilkan mesej permulaan/amaran PHP tersirat.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_reporting
或display_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: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:
Adalah yang terbaik untuk menjadi fungsi praktikal yang mencetak mesej pengguna Jika
header()
gagal.Penimbalan output sebagai penyelesaian
PHPPenimbalan Outputadalah 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.
output_buffering=
Namun, tetapan membantu. Konfigurasikannya dalamphp.iniAtau melalui.htaccessMalah.user.iniPersediaan 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.
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 sebelumrender.
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 jugaContoh penggunaan asasDalam 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.inisudah 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.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 halaTersedia untuk ubah hala halaman:
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. )
Kenapa
setcookie()
和session_start()
juga terjejassetcookie()
和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