Podczas uruchamiania skryptu pojawia się kilka takich błędów:
Ostrzeżenie: Nie można modyfikować informacji nagłówka - nagłówki już wysłane przez ( wyjście rozpoczęto w /some/file.php:12 ) w /some/file.php w linii 23
Wiersze wymienione w komunikatach o błędach zawierają header()
i setcookie()
wywołania.
Co mogłoby być tego przyczyną? I jak to naprawić?
ob_start
iob_end_clean()
może okazać się przydatny tutaj). Następnie możesz ustawić ciasteczko lub sesję równe,ob_get_contents()
a następnie użyćob_end_clean()
do wyczyszczenia bufora.safeRedirect
funkcji w mojej bibliotece PHP: github.com/heinkasner/PHP-Library/blob/master/extra.phpUTF-8
, aleUTF-8 (Without BOM)
~~~~~~~~~~~Odpowiedzi:
Brak danych wyjściowych przed wysłaniem nagłówków!
Funkcje wysyłające / modyfikujące nagłówki HTTP muszą być wywoływane przed wykonaniem jakiegokolwiek wyniku . summary ⇊ W przeciwnym razie połączenie nie powiedzie się:
Niektóre funkcje modyfikujące nagłówek HTTP to:
header
/header_remove
session_start
/session_regenerate_id
setcookie
/setrawcookie
Dane wyjściowe mogą być:
Nieumyślny:
<?php
lub po?>
Zamierzony:
print
,echo
Oraz inne funkcje wyświetlania produkcji<html>
odcinki przed<?php
kodu.Dlaczego tak się dzieje?
Aby zrozumieć, dlaczego nagłówki muszą być wysyłane przed wyjściem, należy spojrzeć na typową odpowiedź HTTP . Skrypty PHP generują głównie treść HTML, ale także przekazują zestaw nagłówków HTTP / CGI do serwera:
Strona / wyjście zawsze następuje po nagłówkach. PHP musi najpierw przekazać nagłówki do serwera WWW. Może to zrobić tylko raz. Po podwójnym podziale wiersza nie można ich już zmienić.
Gdy PHP odbiera pierwsze wyjście (
print
,echo
,<html>
) będzie opróżnić wszystkich zebranych nagłówków. Następnie może wysłać wszystkie potrzebne dane wyjściowe. Ale wysyłanie kolejnych nagłówków HTTP jest wówczas niemożliwe.Jak dowiedzieć się, gdzie wystąpiło przedwczesne wyjście?
header()
Ostrzeżenie zawiera wszystkie istotne informacje, aby znaleźć przyczynę problemu:Tutaj „wiersz 100” odnosi się do skryptu, w którym
header()
wywołanie nie powiodło się.Uwaga „ wyjście rozpoczęte o ” w nawiasie jest bardziej znacząca. Określa źródło poprzedniej produkcji. W tym przykładzie jest to
auth.php
i linia52
. Właśnie tam trzeba było szukać przedwczesnych wyników.Typowe przyczyny:
Drukuj, echo
Umyślne wyjście
print
iecho
instrukcje zakończą możliwość wysyłania nagłówków HTTP. Aby tego uniknąć, przepływ aplikacji musi zostać zrestrukturyzowany. Użyj funkcji i schematów szablonów. Upewnij się, żeheader()
połączenia są wykonywane przed wypisaniem wiadomości.Funkcje generujące dane wyjściowe obejmują
print
,echo
,printf
,vprintf
trigger_error
,ob_flush
,ob_end_flush
,var_dump
,print_r
readfile
,passthru
,flush
,imagepng
,imagejpeg
między innymi funkcje zdefiniowane przez użytkownika.
Surowe obszary HTML
Nieprzetworzone sekcje HTML w
.php
pliku są również wyprowadzane bezpośrednio. Warunki skrypt, który wywołaheader()
połączenie należy zaznaczyć przed wszelkimi surowych<html>
bloków.Użyj schematu szablonów, aby oddzielić przetwarzanie od logiki wyjściowej.
Wcześniej
<?php
spacje dla ostrzeżeń „skrypt.php wiersz 1 ”Jeśli ostrzeżenie odnosi się do danych wyjściowych w linii
1
, oznacza to przede wszystkim białe znaki , tekst lub HTML przed<?php
tokenem otwierającym .Podobnie może się zdarzyć w przypadku dołączonych skryptów lub sekcji skryptów:
PHP zjada pojedynczy podział wiersza po zamknięciu tagów. Ale to nie zrekompensuje wielu nowych linii, tabulatorów lub spacji przesuniętych w takie luki.
LM UTF-8
Problemem mogą być same łamanie linii i spacje. Ale są też „niewidzialne” sekwencje znaków, które mogą to powodować. Najbardziej znany BOM UTF-8 (Bajt-Znak-Znak), który nie jest wyświetlany przez większość edytorów tekstu. Jest to sekwencja bajtów
EF BB BF
, która jest opcjonalna i nadmiarowa dla dokumentów zakodowanych w UTF-8. PHP musi jednak traktować to jako surowe wyjście. Może pojawiać się jako znaki
na wyjściu (jeśli klient interpretuje dokument jako Latin-1) lub podobne „śmieci”.W szczególności edytory graficzne i środowiska IDE oparte na Javie są nieświadome jego obecności. Nie wizualizują go (zgodnie ze standardem Unicode). Jednak większość programistów i edytorów konsolowych:
Łatwo jest wcześnie rozpoznać problem. Inni redaktorzy mogą zidentyfikować jego obecność w menu pliku / ustawień (Notepad ++ w systemie Windows może zidentyfikować i rozwiązać problem ). Inną opcją sprawdzenia obecności BOM jest uciekanie się do hekseditora . W systemach * nix
hexdump
jest zwykle dostępna wersja graficzna, która upraszcza kontrolę tych i innych problemów:Łatwym rozwiązaniem jest ustawienie edytora tekstu do zapisywania plików jako „UTF-8 (bez BOM)” lub podobnej nomenklatury. Często nowi użytkownicy uciekają się do tworzenia nowych plików i kopiowania i wklejania poprzedniego kodu.
Narzędzia korekcyjne
Istnieją również zautomatyzowane narzędzia do sprawdzania i przepisywania plików tekstowych (
sed
/awk
lubrecode
). W przypadku PHP istniejephptags
tag tidier . Przeredagowuje zamykanie i otwieranie znaczników w długie i krótkie formy, ale z łatwością rozwiązuje także wiodące i końcowe problemy z białymi znakami, Unicode i UTF-x BOM:Używanie całego katalogu włączeń lub projektów jest rozsądne.
Biała spacja po
?>
Jeśli źródło błędu jest wspomniane jako za zamknięciem,
?>
to tutaj zapisano trochę białych znaków lub nieprzetworzonego tekstu. Znacznik końca PHP nie kończy w tym momencie wykonywania skryptu. Wszelkie znaki tekstu / spacji po nim zostaną zapisane jako treść strony.Powszechnie zaleca się, szczególnie początkującym, że końcowe
?>
znaczniki zamykające PHP powinny zostać pominięte. Pozwala to uniknąć niewielkiej części tych przypadków. (Dość częstoinclude()d
sprawcami są skrypty).Źródło błędu wymienione jako „Nieznany w linii 0”
Zazwyczaj jest to rozszerzenie PHP lub php.ini, jeśli żadne źródło błędu nie jest konkretyzowane.
gzip
ustawienie kodowania strumienia lubob_gzhandler
.extension=
moduł podwójnie załadowany generujący domyślny komunikat startowy / ostrzegawczy PHP.Poprzednie komunikaty o błędach
Jeśli inna instrukcja lub wyrażenie PHP powoduje wydrukowanie komunikatu ostrzegawczego lub powiadomienia, jest to również liczone jako przedwczesne wyjście.
W takim przypadku musisz uniknąć błędu, opóźnić wykonanie instrukcji lub ukryć komunikat za pomocą np.
isset()
Lub@()
- gdy albo nie utrudni to późniejszego debugowania.Brak komunikatu o błędzie
Jeśli masz
error_reporting
lubdisplay_errors
wyłączyłeśphp.ini
, nie pojawi się żadne ostrzeżenie. Ale ignorowanie błędów nie spowoduje, że problem zniknie. Nagłówków nadal nie można wysłać po przedwczesnym wyjściu.Dlatego gdy
header("Location: ...")
przekierowania po cichu nie działają, wskazane jest sprawdzenie ostrzeżeń. Ponownie włącz je za pomocą dwóch prostych poleceń na skrypcie wywołania:Lub
set_error_handler("var_dump");
jeśli wszystko inne zawiedzie.Mówiąc o nagłówkach przekierowań, powinieneś często używać takiego idiomu dla końcowych ścieżek kodu:
Najlepiej nawet funkcja użyteczna, która drukuje komunikat użytkownika w przypadku
header()
awarii.Buforowanie danych wyjściowych jako obejście
Buforowanie danych wyjściowych PHPs jest obejściem tego problemu. Często działa niezawodnie, ale nie powinno zastępować właściwej struktury aplikacji i oddzielania danych wyjściowych od logiki sterowania. Jego rzeczywistym celem jest zminimalizowanie porcji przesyłanych na serwer internetowy.
output_buffering=
Ustawienie mimo to może pomóc. Skonfiguruj go w php.ini lub poprzez .htaccess, a nawet .user.ini w nowoczesnych konfiguracjach FPM / FastCGI.Włączenie go pozwoli PHP buforować dane wyjściowe zamiast natychmiastowego przekazywania ich do serwera WWW. PHP może zatem agregować nagłówki HTTP.
Może być również zaangażowany w wywołanie na
ob_start();
szczycie skryptu wywołania. Który jednak jest mniej niezawodny z wielu powodów:Nawet jeśli
<?php ob_start(); ?>
uruchamia się pierwszy skrypt, białe znaki lub LM mogą być wcześniej tasowane, co czyni go nieskutecznym .Może ukrywać białe znaki dla danych wyjściowych HTML. Ale gdy tylko logika aplikacji próbuje wysłać zawartość binarną (na przykład wygenerowany obraz), buforowane zbędne dane wyjściowe stają się problemem. (Konieczne
ob_clean()
jako dalsze obejście).Bufor ma ograniczony rozmiar i może łatwo zostać przekroczony, gdy zostanie pozostawiony domyślny. I nie jest to również rzadkie zjawisko, trudne do wyśledzenia, kiedy to się dzieje.
Oba podejścia mogą zatem stać się zawodne - w szczególności przy przełączaniu między konfiguracjami programistycznymi i / lub serwerami produkcyjnymi. Dlatego buforowanie danych wyjściowych jest powszechnie uważane za zwykłe rozwiązanie.
Zobacz także przykład użycia podstawowego w instrukcji oraz dodatkowe zalety i wady:
Ale działało na drugim serwerze !?
Jeśli wcześniej nie otrzymałeś ostrzeżenia w nagłówkach, oznacza to, że ustawienie bufora wyjściowego php.ini uległo zmianie. Prawdopodobnie jest nieskonfigurowany na bieżącym / nowym serwerze.
Sprawdzanie za pomocą
headers_sent()
Zawsze możesz użyć
headers_sent()
do sprawdzenia, czy nadal można ... wysłać nagłówki. Co jest przydatne do warunkowego wydrukowania informacji lub zastosowania innej logiki zastępczej.Przydatne obejścia zastępcze to:
<meta>
Tag HTMLJeśli aplikacja jest strukturalnie trudna do naprawienia, to łatwym (ale nieco nieprofesjonalnym) sposobem na umożliwienie przekierowań jest wstrzykiwanie
<meta>
znacznika HTML . Przekierowanie można osiągnąć za pomocą:Lub z krótkim opóźnieniem:
Prowadzi to do nieprawidłowego kodu HTML, jeśli zostanie wykorzystany poza
<head>
sekcją. Większość przeglądarek nadal to akceptuje.Przekierowanie JavaScript
Alternatywnie do przekierowań stron można użyć przekierowania JavaScript :
Chociaż jest to często bardziej zgodne z HTML niż
<meta>
obejście, powoduje to poleganie na klientach obsługujących JavaScript.Oba podejścia powodują jednak akceptowalne awarie w przypadku niepowodzenia autentycznych wywołań nagłówka HTTP (). Idealnie byłoby zawsze połączyć to z przyjazną dla użytkownika wiadomością i klikalnym linkiem w ostateczności. (Na przykład to, co robi rozszerzenie PECL http_redirect () .)
Dlaczego
setcookie()
isession_start()
to również dotyczyZarówno
setcookie()
isession_start()
trzeba wysłaćSet-Cookie:
nagłówek HTTP. Dlatego obowiązują te same warunki i podobne komunikaty o błędach będą generowane w przypadku przedwczesnych sytuacji wyjściowych.(Oczywiście wpływają na to wyłączone pliki cookie w przeglądarce, a nawet problemy z serwerem proxy. Funkcjonalność sesji oczywiście zależy również od wolnego miejsca na dysku i innych ustawień php.ini itp.)
Dalsze linki
źródło
?>
z końca plików php jest zwykle dobrą praktyką, która pomaga również zminimalizować te błędy. Niepożądane białe znaki nie pojawią się na końcu plików i nadal będziesz mógł dodać nagłówki do odpowiedzi później. Jest to również przydatne, jeśli korzystasz z buforowania danych wyjściowych i nie chciałbyś widzieć dodanej niechcianej spacji na końcu części generowanych przez dołączone pliki.Ten komunikat o błędzie jest uruchamiany, gdy cokolwiek zostanie wysłane przed wysłaniem nagłówków HTTP (za pomocą
setcookie
lubheader
). Typowe przyczyny wypisywania czegoś przed nagłówkami HTTP to:Przypadkowe białe znaki, często na początku lub na końcu plików, takie jak to:
Aby tego uniknąć, po prostu pomiń zamknięcie
?>
- i tak nie jest wymagane.3F 3C
. Możesz bezpiecznie usunąć BOMEF BB BF
od początku plików.echo
,printf
,readfile
,passthru
, kod przed<?
etc.display_errors
właściwość php.ini. Zamiast zawieszać się na błędzie programisty, php po cichu naprawia błąd i wysyła ostrzeżenie. Chociaż możesz modyfikować konfiguracjedisplay_errors
lub raportowanie błędów , powinieneś raczej rozwiązać problem.Typowe przyczyny to dostęp do niezdefiniowanych elementów tablicy (np.
$_POST['input']
Bez użyciaempty
lub wisset
celu sprawdzenia, czy dane wejściowe są ustawione), lub użycie niezdefiniowanej stałej zamiast literału łańcucha (jak w$_POST[input]
, zwróć uwagę na brakujące cudzysłowy).Włączenie buforowania danych wyjściowych powinno rozwiązać problem; wszystkie dane wyjściowe po wywołaniu
ob_start
są buforowane w pamięci do momentu zwolnienia bufora, npob_end_flush
. za pomocą .Chociaż buforowanie danych wyjściowych pozwala uniknąć problemów, należy naprawdę ustalić, dlaczego aplikacja wysyła treść HTTP przed nagłówkiem HTTP. To byłoby jak odbieranie telefonu i omawianie twojego dnia i pogody przed powiadomieniem dzwoniącego, że ma zły numer.
źródło
Ten błąd występował już wiele razy i jestem pewien, że wszyscy programiści PHP przynajmniej raz otrzymali ten błąd.
Możliwe rozwiązanie 1
Ten błąd mógł być spowodowany pustymi spacjami przed rozpoczęciem pliku lub po jego zakończeniu. Nie powinno ich tu być.
Np. NIE POWINNY BYĆ TUTAJ NIEPRZERWANE MIEJSCA
Sprawdź wszystkie pliki związane z plikiem, który powoduje ten błąd.
Uwaga: Czasami EDITOR (IDE) jak gedit (domyślny edytor linux) dodaje jedną pustą linię do pliku zapisu. To nie powinno się zdarzyć. Jeśli używasz Linuksa. możesz użyć edytora VI, aby usunąć spację / linie po?> na końcu strony.
Możliwe rozwiązanie 2: Jeśli tak nie jest, użyj ob_start do buforowania danych wyjściowych:
Spowoduje to włączenie buforowania danych wyjściowych, a nagłówki zostaną utworzone po buforowaniu strony.
źródło
ob_start()
po prostu ukrywa problem; nie używaj go do rozwiązania tego konkretnego problemu.ob_start()
, to co powinienem zrobić, aby rozwiązać ten problem:Headers already sent
ob_start()
nie „ukrywa” problemu, rozwiązuje problem.Zamiast dolnej linii
pisać
lub
To na pewno rozwiąże twój problem. Napotkałem ten sam problem, ale rozwiązałem ten problem, pisząc lokalizację nagłówka w powyższy sposób.
źródło
Ty robisz
przed ustawieniem plików cookie, co jest niedozwolone. Nie możesz wysłać żadnych danych wyjściowych przed nagłówkami, nawet pustej linii.
źródło
Jest tak z powodu tej linii:
Nie należy nic drukować / echa przed wysłaniem nagłówków.
źródło
CZĘSTE PROBLEMY:
(skopiowane z: źródło )
====================
1)
echo..
przedheader(.......);
poleceniem nie powinno być żadnych wyników (tj. Kodów HTML) .2) usuń wszelkie spacje (lub znaki nowej linii ) przed
<?php
i po?>
tagach.3) ZŁOTA ZASADA! - sprawdź, czy ten plik php (a także, jeśli masz
include
inne pliki) ma UTF8 bez kodowania BOM (a nie tylko UTF-8 ). Jest to problem w wielu przypadkach (ponieważ plik zakodowany w UTF8 ma na początku pliku php coś specjalnego, czego edytor tekstowy nie pokazuje) !!!!!!!!!!!4) Po
header(...);
musisz użyćexit;
5) zawsze używaj referencji 301 lub 302:
6) Włącz raportowanie błędów i znajdź błąd. Twój błąd może być spowodowany niedziałającą funkcją. Po włączeniu raportowania błędów zawsze należy najpierw naprawić najwyższy błąd. Na przykład może to być „Ostrzeżenie: date_default_timezone_get (): poleganie na ustawieniach systemowych strefy czasowej systemu nie jest bezpieczne”. - następnie w dół możesz zobaczyć błąd „nagłówki nie zostały wysłane”. Po naprawieniu błędu najwyższego (1.) ponownie załaduj stronę. Jeśli nadal masz błędy, ponownie napraw błąd najwyższy.
7) Jeśli żadna z powyższych nie pomoże, użyj przekierowania JAVSCRIPT (jednak zdecydowanie niezalecana metoda), może być ostatnią szansą w niestandardowych przypadkach ...:
źródło
301
lub302
ważne?Prosta wskazówka:
<?php
może to powodować prosta spacja (lub niewidoczny specjalny znak) w skrypcie, tuż przed pierwszym tagiem! Zwłaszcza, gdy pracujesz w zespole i ktoś używa „słabego” IDE lub popełnił błędy w plikach z dziwnymi edytorami tekstu.Widziałem te rzeczy;)
źródło
Kolejna zła praktyka może wywoływać ten problem, który nie został jeszcze określony.
Zobacz ten fragment kodu:
Wszystko w porządku, prawda?
Co jeśli „a_important_file.php” to:
To nie zadziała? Dlaczego? Ponieważ już generowana jest nowa linia.
Teraz, choć nie jest to częsty scenariusz, co zrobić, jeśli używasz frameworka MVC, który ładuje dużo plików przed przekazaniem rzeczy do kontrolera? To nie jest rzadki scenariusz. Przygotuj się na to.
Z PSR-2 2.2:
Unix LF (linefeed) line ending
.single blank line
.omitted
z plików zawierającychonly php
Uwierz mi, przestrzeganie tych standardów może uratować Ci wiele godzin życia :)
źródło
?>
znacznika zamykającego w żadnym plikuCR LF
(typowego końca linii Windows). Rozwiązuję go, pobierając oryginalny plik z repozytorium Wordpress, który maLF
(Linux na końcu linii) zamiast,CR LF
a także przeniosłem moją funkcję do funkcji functions.php. Na podstawie: bit.ly/1Gh6mzN?>
<?php
, usuwaniem i dodawaniem pojedynczej pustej linii, dodawaniem i pomijaniem tagu zamykającego?>
. W Windows + Wamp wszystkie te kombinacje działają dobrze. Wierd ...Czasami, gdy proces deweloperski ma zarówno stacje robocze WIN, jak i systemy LINUX (hosting), aw kodzie nie widać żadnych danych wyjściowych przed powiązaną linią, może to być formatowanie pliku i brak zakończenia linii Unix LF (linefeed) .
To, co zwykle robimy, aby to szybko naprawić, to zmiana nazwy pliku i w systemie LINUX utwórz nowy plik zamiast o zmienionej nazwie, a następnie skopiuj do niego zawartość. Wiele razy to rozwiązuje problem, ponieważ niektóre pliki utworzone w WIN po przeniesieniu do hostingu powodują ten problem.
Ta poprawka jest łatwą poprawką dla witryn, którymi zarządzamy przez FTP, i czasami może zaoszczędzić trochę czasu naszym nowym członkom zespołu.
źródło
Zasadniczo ten błąd pojawia się, gdy wysyłamy nagłówek po echu lub drukowaniu. Jeśli ten błąd pojawia się na określonej stronie, upewnij się, że strona nic nie echa przed wywołaniem
start_session()
.Przykład nieprzewidywalnego błędu:
Jeszcze jeden przykład:
Wniosek: Nie wypisuj żadnego znaku przed wywołaniem
session_start()
aniheader()
nie działa on nawet na spację lub znak nowej liniiźródło