Üstbilgileri göndermeden önce çıktı yok!
HTTP üstbilgileri gönderen / değiştiren işlevler, herhangi bir çıktı yapılmadan önce çağrılmalıdır .
summary ⇊
Aksi takdirde çağrı başarısız olur:
Uyarı: Başlık bilgileri değiştirilemiyor - başlıklar zaten gönderildi (çıktı komut dosyasında başladı : satır )
HTTP üstbilgisini değiştiren bazı işlevler şunlardır:
Çıktı olabilir:
kasıtlı:
print
, echo
Ve diğer fonksiyonları üretim çıkışı
- Ham
<html>
bölümler önceki <?php
kod.
Neden oluyor?
Çıktılardan önce başlıkların neden gönderilmesi gerektiğini anlamak için tipik bir HTTP
yanıtına bakmak gerekir . PHP komut dosyaları temel olarak HTML içeriği oluşturur, ancak web sunucusuna bir dizi HTTP / CGI üstbilgisi iletir:
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>
Sayfa / çıktı her zaman başlıkları takip eder. PHP önce üstbilgileri web sunucusuna iletmelidir. Bunu sadece bir kez yapabilir. Çift hat kırılmasından sonra onları daha fazla değiştirebilir.
PHP ilk çıkışını aldığında ( print
, echo
, <html>
) o olacaktır
temizlemek tüm toplanan başlıklarını. Daha sonra istediği tüm çıktıları gönderebilir. Ancak, daha fazla HTTP başlığı göndermek imkansızdır.
Prematüre çıktının nerede meydana geldiğini nasıl öğrenebilirsiniz?
header()
Uyarı sorun nedenini bulmak için tüm ilgili bilgileri içerir:
Uyarı: Üstbilgi bilgileri değiştirilemiyor - 100. satırdaki /www/usr2345/htdocs/index.php adresinde zaten gönderilen
(çıkış / www / usr2345 / htdocs / auth.php : 52 adresinde başlayan ) üstbilgiler
Burada "satır 100", header()
çağrının başarısız olduğu komut dosyasına karşılık gelir .
Parantez içindeki " çıktı başlangıç " notu daha önemlidir. Önceki çıktının kaynağını belirtir. Bu örnekte bu auth.php
ve çizgi52
. Bu, erken çıktı aramak zorunda kaldığınız yerdi.
Tipik nedenleri:
Baskı, yankı
Kasıtlı çıktılar print
ve echo
ifadeler HTTP üstbilgileri gönderme fırsatını sonlandıracaktır. Bunu önlemek için uygulama akışı yeniden yapılandırılmalıdır. İşlevleri
ve şablon düzenlerini kullanın . header()
Çağrıların daha önce yapılmasını sağlayınMesajlar yazılmadan yapıldığından .
Çıktı üreten işlevler şunları içerir:
print
, echo
, printf
,vprintf
trigger_error
, ob_flush
, ob_end_flush
, var_dump
,print_r
readfile
, passthru
, flush
, imagepng
,imagejpeg
diğerleri ve kullanıcı tanımlı işlevler arasında.
Ham HTML alanları
Bir .php
dosyadaki ayrıştırılmamış HTML bölümleri de doğrudan çıktıdır. Bir header()
çağrıyı tetikleyecek komut dosyası koşulları, herhangi bir ham <html>
bloktan önce not edilmelidir .
<!DOCTYPE html>
<?php
// Too late for headers already.
İşlemi çıktı mantığından ayırmak için şablonlama şeması kullanın.
- Form işleme kodunu komut dosyalarının üstüne yerleştirin.
- İletileri ertelemek için geçici dize değişkenleri kullanın.
- Gerçek çıkış mantığı ve karıştırılmış HTML çıktısı son olarak gelmelidir.
Daha önce <?php
"script.php line 1 " uyarıları için boşluk
Uyarı, satırdaki çıktıya atıfta 1
bulunuyorsa, çoğunlukla açılış belirtecinden önce boşluk , metin veya HTML önde gelir <?php
.
<?php
# There's a SINGLE space/newline before <? - Which already seals it.
Benzer şekilde, ekli komut dosyaları veya komut dosyası bölümleri için de oluşabilir:
?>
<?php
PHP aslında yakın etiketlerden sonra tek bir satır sonu yiyor . Ancak, bu tür boşluklara kaydırılmış birden fazla satırsonu veya sekme veya boşluk telafi etmez.
UTF-8 Malzeme Listesi
Çizgi çizgileri ve boşluklar tek başına bir sorun olabilir. Ancak buna neden olabilecek "görünmez" karakter dizileri de vardır. En ünlü
UTF-8 BOM (Byte-Order-Mark)
metin editörleri tarafından gösterilmez. EF BB BF
UTF-8 kodlu belgeler için isteğe bağlı ve yedekli bayt dizisidir . Ancak PHP bunu ham çıktı olarak kabul etmek zorundadır. 
Çıktıdaki karakterler (istemci belgeyi Latin-1 olarak yorumlarsa) veya benzer bir "çöp" olarak görünebilir .
Özellikle grafik editörler ve Java tabanlı IDE'ler varlığından habersizdir. Görselleştirmezler (Unicode standardı tarafından zorunlu tutulur). Bununla birlikte, çoğu programcı ve konsol editörleri:
Orada sorunu erken fark etmek kolaydır. Diğer editörler bir dosya / ayarlar menüsünde varlığını belirleyebilir (Windows'ta Notepad ++ sorunu tanımlayıp
çözebilir ), Malzeme Listelerinin varlığını denetlemek için başka bir seçenek bir hexeditor'a başvurmaktır . Açık * nix sistemlerihexdump
genellikle, bunları ve diğer sorunları denetlemeyi kolaylaştıran bir grafik varyant değilse, kullanılabilir:
Kolay bir düzeltme, metin düzenleyicisini dosyaları "UTF-8 (BOM yok)" veya benzeri bir adlandırma olarak kaydedecek şekilde ayarlamaktır. Çoğu zaman yeni gelenler yeni dosyalar oluşturmaya ve önceki kodu kopyalayıp yapıştırmaya başvururlar.
Düzeltme yardımcı programları
Metin dosyalarını ( sed
/awk
veya recode
) incelemek ve yeniden yazmak için otomatik araçlar da vardır . PHP için özellikle phptags
tag tidier var . Yakın ve açık etiketleri uzun ve kısa formlara yeniden yazar, ancak önde gelen ve sondaki boşluk, Unicode ve UTF-x BOM sorunlarını kolayca düzeltir:
phptags --whitespace *.php
Tüm bir ekleme veya proje dizininde kullanmak akılcı.
Sonra boşluk ?>
Hata kaynağı kapanışın?>
arkasında belirtilirse
, burada bazı boşluk veya ham metin yazılır. PHP son işaretçisi bu noktada kod yürütülmesini sonlandırmaz. Sonraki metin / boşluk karakterleri hala sayfa içeriği olarak yazılacaktır.
Yaygın olarak, özellikle yeni gelenler için, takip eden ?>
PHP kapatma etiketlerinin atlanması önerilir . Bu , bu davaların küçük bir kısmını kaçırmaktadır . (Oldukça yaygın include()d
senaryolar suçludur.)
"0 satırında bilinmeyen" olarak belirtilen hata kaynağı
Herhangi bir hata kaynağı somutlaştırılmazsa, genellikle bir PHP uzantısı veya php.ini ayarıdır.
- Zaman zaman
gzip
akış kodlama ayarı
veyaob_gzhandler
.
- Ancak
extension=
, örtük bir PHP başlatma / uyarı mesajı üreten herhangi bir çift yüklü modül de olabilir .
Önceki hata mesajları
Başka bir PHP deyimi veya ifadesi bir uyarı iletisine veya bildirimin yazdırılmasına neden olursa, bu da erken çıktı olarak sayılır.
Bu durumda, hatadan kaçınmanız, deyimin yürütülmesini geciktirmeniz veya mesajı örneğin isset()
veya @()
- daha sonra hata ayıklamayı engellemediğinde bastırmanız gerekir
.
Hata mesajı yok
Eğer varsa error_reporting
veya display_errors
özürlü başına php.ini
, o zaman hiçbir uyarı görünecektir. Ancak hataları görmezden gelmek sorunu ortadan kaldırmaz. Başlıklar, erken çıktıdan sonra gönderilemez.
Bu nedenle header("Location: ...")
yönlendirmeler sessizce başarısız olduğunda , uyarıları incelemek çok tavsiye edilir. Bunları çağırma komut dosyasının üstündeki iki basit komutla yeniden etkinleştirin:
error_reporting(E_ALL);
ini_set("display_errors", 1);
Ya set_error_handler("var_dump");
da her şey başarısız olursa.
Yönlendirme başlıklarından bahsetmişken, son kod yolları için genellikle aşağıdaki gibi bir deyim kullanmalısınız:
exit(header("Location: /finished.html"));
Tercihen, header()
arıza durumunda bir kullanıcı mesajı yazdıran bir yardımcı program işlevi bile .
Geçici çözüm olarak çıktı arabelleğe alma
PHP'lerin çıktı arabelleğe alma
bu sorunu hafifletmek için bir çözümdür . Genellikle güvenilir bir şekilde çalışır, ancak uygun uygulama yapılandırması ve çıktıyı kontrol mantığından ayırmanın yerine geçmemelidir. Asıl amacı, web sunucusuna yığın aktarımlarını en aza indirmektir.
output_buffering=
Ayar yine yardımcı olabilir. Php.ini dosyasında
veya modern FPM / FastCGI kurulumlarında .htaccess
veya .user.ini dosyasında yapılandırın .
Etkinleştirilmesi, PHP'nin web sunucusuna anında aktarmak yerine çıktıyı arabelleğe almasına izin verir. PHP böylece HTTP üstbilgilerini toplayabilir.
Aynı şekilde ob_start();
çağırma komut dosyasının üstüne bir çağrı ile de meşgul olabilir . Bununla birlikte, birçok nedenden dolayı daha az güvenilirdir:
<?php ob_start(); ?>
İlk komut dosyasını başlatsa bile , boşluk veya ürün ağacı daha önce karıştırılabilir ve bu da onu etkisiz hale getirir .
HTML çıktısı için boşlukları gizleyebilir. Ancak uygulama mantığı ikili içerik göndermeye çalışır (örneğin, oluşturulan bir görüntü), arabelleğe alınmış harici çıktı bir sorun haline gelir. (Daha ileri bir ob_clean()
çözüm olarak gerekli.)
Arabellek boyutu sınırlıdır ve varsayılan değerlere bırakıldığında kolayca taşabilir. Ve bu da nadir bir durum değil,
gerçekleştiğinde izlenmesi zor .
Bu nedenle, her iki yaklaşım da özellikle geliştirme kurulumları ve / veya üretim sunucuları arasında geçiş yaparken güvenilmez olabilir. Bu nedenle çıktı tamponlaması yaygın olarak sadece bir koltuk değneği / kesinlikle bir çözüm olarak kabul edilir.
Ayrıca
kılavuzdaki temel kullanım örneğine bakın ve daha fazla avantaj ve dezavantaj için:
Ama diğer sunucuda çalıştı !?
Üstbilgileri daha önce uyarmadıysanız , çıktı arabelleğe alma php.ini ayarı
değişti. Muhtemelen mevcut / yeni sunucuda yapılandırılmamış.
İle kontrol headers_sent()
headers_sent()
Başlık göndermek için hala mümkünse her zaman araştırma yapabilirsiniz . Bu, bir bilgiyi koşullu olarak yazdırmak veya diğer yedek mantığı uygulamak için kullanışlıdır.
if (headers_sent()) {
die("Redirect failed. Please click on this link: <a href=...>");
}
else{
exit(header("Location: /user.php"));
}
Yararlı yedek çözümler şunlardır:
HTML <meta>
etiketi
Uygulamanızın yapısal olarak düzeltilmesi zorsa, yönlendirmelere izin vermenin kolay (ancak biraz profesyonel olmayan) bir yolu bir HTML <meta>
etiketi enjekte etmektir
. Bir yönlendirme aşağıdakilerle gerçekleştirilebilir:
<meta http-equiv="Location" content="http://example.com/">
Veya kısa bir gecikmeyle:
<meta http-equiv="Refresh" content="2; url=../target.html">
Bu, <head>
bölümün ötesinde kullanıldığında geçersiz HTML'ye yol açar . Çoğu tarayıcı hala kabul ediyor.
JavaScript yönlendirmesi
Alternatif
olarak sayfa yönlendirmeleri için bir JavaScript yönlendirmesi kullanılabilir:
<script> location.replace("target.html"); </script>
Bu genellikle <meta>
geçici çözümden daha HTML uyumlu olsa da, JavaScript özellikli istemcilere güvenir.
Bununla birlikte, her iki yaklaşım da orijinal HTTP header () çağrıları başarısız olduğunda kabul edilebilir geri dönüşler yapar. İdeal olarak bunu her zaman kullanıcı dostu bir mesaj ve son çare olarak tıklanabilir bağlantı ile birleştirirsiniz. (Örneğin, http_redirect ()
PECL uzantısının yaptığı nedir.)
Neden setcookie()
ve session_start()
ayrıca etkilenir
Her ikisi de setcookie()
ve session_start()
bir Set-Cookie:
HTTP üstbilgisi göndermeniz gerekir . Dolayısıyla aynı koşullar geçerlidir ve erken çıkış durumları için benzer hata mesajları üretilir.
(Elbette tarayıcıdaki devre dışı çerezlerden ve hatta proxy sorunlarından da etkilenirler. Oturum işlevselliği açıkça boş disk alanına ve diğer php.ini ayarlarına vb. Bağlıdır.)
Diğer bağlantılar