Bij het uitvoeren van mijn script krijg ik verschillende foutmeldingen zoals:
Waarschuwing: kan header-informatie niet wijzigen – headers die al zijn verzonden door (uitvoer gestart op /some/file.php:12) in /some/file.phpop regel 23
De regels in de foutmeldingen bevatten header()
en setcookie()
aanroepen.
Wat zou hiervan de reden kunnen zijn? En hoe dit op te lossen?
Antwoord 1, autoriteit 100%
Geen uitvoer voordat kopteksten worden verzonden!
Functies die HTTP-headers verzenden/wijzigen, moeten worden aangeroepen voordat er uitvoer wordt gemaakt.
samenvatting?
Anders mislukt de oproep:
Waarschuwing: kan header-informatie niet wijzigen – headers al verzonden (uitvoer gestart op script:line)
Sommige functies die de HTTP-header wijzigen zijn:
Uitvoer kan zijn:
-
Onbedoeld:
- Witruimte voor
<?php
of na?>
- Het UTF-8 Byte Order Markspecifiek
- Vorige foutmeldingen of meldingen
- Witruimte voor
-
Opzettelijk:
print
,echo
en andere functies die output produceren- Onbewerkte
<html>
secties voorafgaand aan<?php
code.
Waarom gebeurt het?
Om te begrijpen waarom headers moeten worden verzonden voordat ze worden uitgevoerd, is dit nodig
om naar een typische HTTPte kijken
antwoord. PHP-scripts genereren voornamelijk HTML-inhoud, maar geven ook a
set HTTP/CGI-headers naar de webserver:
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>
De pagina/uitvoer volgt altijdde headers. PHP moet slagen voor de
headers eerst naar de webserver. Dat kan het maar één keer.
Na de dubbele regelafbreking kan het ze nooit meer wijzigen.
Als PHP de eerste uitvoer ontvangt (print
, echo
, <html>
), zal het
spoelalle verzamelde headers. Daarna kan het alle output verzenden
het wil. Maar het verzenden van verdere HTTP-headers is dan onmogelijk.
Hoe kom je erachter waar de voortijdige output plaatsvond?
De header()
waarschuwing bevat alle relevante informatie om
zoek de oorzaak van het probleem:
Waarschuwing: kan header-informatie niet wijzigen – headers zijn al verzonden door
(uitvoer gestart op/www/usr2345/htdocs/auth.php:52) in
/www/usr2345/htdocs/index.php online 100
Hier verwijst “regel 100” naar het script waar de header()
aanroepis mislukt.
De opmerking “uitvoer begonnen bij” tussen haakjes is belangrijker.
Het geeft de bron van de vorige uitvoer aan. In dit voorbeeld is dat auth.php
en regel 52
. Daar moest je zoeken naar voortijdige output.
Typische oorzaken:
-
Afdrukken, echo
Opzettelijke uitvoer van
print
– enecho
-instructies zal de mogelijkheid om HTTP-headers te verzenden beëindigen. Om dat te voorkomen, moet de applicatiestroom worden geherstructureerd. Gebruik functies
en sjabloonschema’s. Zorg ervoor datheader()
-aanroepen plaatsvinden vóórberichten
worden uitgeschreven.Functies die output produceren zijn onder andere
print
,echo
,printf
,vprintf
trigger_error
,ob_flush
,ob_end_flush
,var_dump
,print_r
readfile
,passthru
,flush
,imagepng
,imagejpeg
onder andere en door de gebruiker gedefinieerde functies.
-
Onbewerkte HTML-gebieden
Ongeparseerde HTML-secties in een
.php
-bestand worden ook direct uitgevoerd.
Scriptvoorwaarden die eenheader()
-aanroep activeren, moeten worden genoteerd
vóór elkeonbewerkte<html>
blokken.<!DOCTYPE html> <?php // Too late for headers already.
Gebruik een sjabloonschema om verwerking te scheiden van uitvoerlogica.
- Plaats formulierverwerkingscode bovenop scripts.
- Gebruik tijdelijke tekenreeksvariabelen om berichten uit te stellen.
- De feitelijke uitvoerlogica en de gemengde HTML-uitvoer moeten als laatste volgen.
-
Witruimte voor
<?php
voor “script.php regel 1” waarschuwingenAls de waarschuwing verwijst naar uitvoer inline
1
, dan is het meestal
leidende witruimte, tekst of HTML vóór het openingstoken<?php
.<?php # There's a SINGLE space/newline before <? - Which already seals it.
Het kan ook voorkomen voor toegevoegde scripts of scriptsecties:
?> <?php
PHP eet zelfs een enkeleregeleinde op na close-tags. Maar het zal niet
compenseer meerdere nieuwe regels of tabs of spaties die in dergelijke gaten zijn verschoven. -
UTF-8 stuklijst
Alleen regeleinden en spaties kunnen een probleem zijn. Maar er zijn ook “onzichtbare”
tekenreeksen die dit kunnen veroorzaken. meest beroemde de
UTF-8 BOM(Byte-Order-Mark)
die niet wordt weergegeven door de meeste teksteditors. Het is de bytereeksEF BB BF
, die optioneel en overbodig is voor UTF-8-gecodeerde documenten. PHP moet het echter als onbewerkte uitvoer behandelen. Het kan verschijnen als de tekensi»?
in de uitvoer (als de klant het document interpreteert als Latin-1) of vergelijkbaar “vuilnis”.Vooral grafische editors en op Java gebaseerde IDE’s zijn zich niet bewust van zijn
aanwezigheid. Ze visualiseren het niet (verplicht door de Unicode-standaard).
De meeste programmeurs en console-editors doen dit echter wel:Daar is het gemakkelijk om het probleem in een vroeg stadium te herkennen. Andere redacteuren kunnen identificeren:
zijn aanwezigheid in een bestand/instellingenmenu (Notepad++ op Windows kan identificeren en
het probleem oplossen),
Een andere optie om de aanwezigheid van de stuklijst te inspecteren is een hexeditorin te schakelen.
Op *nix-systemen ishexdump
meestal beschikbaar,
zo niet een grafische variant die het controleren van deze en andere problemen vereenvoudigt:Een eenvoudige oplossing is om de teksteditor in te stellen om bestanden op te slaan als “UTF-8 (geen stuklijst)”
of vergelijkbaar met een dergelijke nomenclatuur. Vaak nemen nieuwkomers anders hun toevlucht tot het maken van nieuwe bestanden en kopiëren en plakken ze de vorige code er gewoon weer in.Correctie-hulpprogramma’s
Er zijn ook geautomatiseerde tools om tekstbestanden te onderzoeken en te herschrijven
(sed
/awk
ofrecode
).
Specifiek voor PHP is er dephptags
tag tidier.
Het herschrijft dichte en open tags in lange en korte vormen, maar ook gemakkelijk
lost problemen met voorloop- en achterliggende witruimte, Unicode en UTF-x stuklijst op:phptags --whitespace *.php
Het is veilig om te gebruiken voor een hele include of projectdirectory.
-
Witruimte na
?>
Als de foutbron wordt vermeld als achter de
afsluiten?>
dan is hier wat witruimte of de onbewerkte tekst uitgeschreven.
De PHP-eindmarkering beëindigt de uitvoering van het script op dit punt niet. Eventuele tekst/spatietekens daarna worden uitgeschreven als pagina-inhoud
nog steeds.Het wordt vaak aangeraden, met name aan nieuwkomers, om
?>
PHP
close-tags moeten worden weggelaten. Dit vermijdteen klein deel van deze gevallen.
(Vaak zijninclude()d
-scripts de boosdoener.) -
Foutbron vermeld als “Onbekend op regel 0”
Het is meestal een PHP-extensie of php.ini-instelling als er geen foutbron is
is geconcretiseerd.- Het is af en toe de
gzip
stream-coderingsinstelling
of deob_gzhandler
. - Maar het kan ook een dubbel geladen
extension=
module zijn
het genereren van een impliciet PHP-opstart-/waarschuwingsbericht.
- Het is af en toe de
-
Vorige foutmeldingen
Als een andere PHP-instructie of -expressie een waarschuwingsbericht veroorzaakt of
bericht wordt afgedrukt, dat geldt ook als voortijdige uitvoer.In dit geval moet u de fout vermijden,
vertraag de uitvoering van de instructie, of onderdruk het bericht met b.v.
isset()
of@()
–
wanneer een van beide het debuggen later niet belemmert.
Geen foutmelding
Als je error_reporting
of display_errors
hebt uitgeschakeld per php.ini
,
dan verschijnt er geen waarschuwing. Maar fouten negeren zal het probleem niet oplossen
weg. Headers kunnen nog steeds niet worden verzonden na voortijdige uitvoer.
Dus wanneer header("Location: ...")
omleidingen stil mislukken, is het erg
raadzaam om te zoeken naar waarschuwingen. Schakel ze opnieuw in met twee eenvoudige commando’s
bovenop het aanroepscript:
error_reporting(E_ALL);
ini_set("display_errors", 1);
Of set_error_handler("var_dump");
als al het andere faalt.
Over omleidingsheaders gesproken, je zou vaak een idioom als . moeten gebruiken
dit voor definitieve codepaden:
exit(header("Location: /finished.html"));
Bij voorkeur zelfs een hulpprogramma-functie, die een gebruikersbericht afdrukt
in het geval van header()
fouten.
Uitvoerbuffering als tijdelijke oplossing
PHP’s uitvoerbuffering
is een oplossing om dit probleem te verhelpen. Het werkt vaak betrouwbaar, maar zou dat niet moeten doen
vervanging voor een juiste applicatie-structurering en scheiding van output en controle
logica. Het eigenlijke doel is het minimaliseren van gebundelde overdrachten naar de webserver.
-
De
output_buffering=
instelling kan echter helpen.
Configureer het in de php.ini
of via .htaccess
of zelfs .user.iniop
moderne FPM/FastCGI-instellingen.
Als u dit inschakelt, kan PHP de uitvoer bufferen in plaats van deze onmiddellijk door te geven aan de webserver. PHP kan dus HTTP-headers samenvoegen. -
Het kan ook worden geactiveerd door een oproep naar
ob_start();
bovenop het aanroepscript. Wat echter om meerdere redenen minder betrouwbaar is:-
Zelfs als
<?php ob_start(); ?>
start het eerste script, witruimte of a
Stuklijst kan eerder worden geschud, het renderen niet effectief. -
Het kan witruimte verbergen voor HTML-uitvoer. Maar zodra de applicatielogica probeert binaire inhoud te verzenden (bijvoorbeeld een gegenereerde afbeelding),
de gebufferde externe uitvoer wordt een probleem. (Vereistob_clean()
als een verdere oplossing.) -
De buffer is beperkt in omvang en kan gemakkelijk worden overschreden als de standaardwaarden worden behouden.
En dat komt ook niet zelden voor, moeilijk op te sporen
wanneer het gebeurt.
-
Beide benaderingen kunnen daarom onbetrouwbaar worden, vooral bij het schakelen tussen
ontwikkelingsopstellingen en/of productieservers. Dit is de reden waarom outputbuffering is:
algemeen beschouwd als slechts een kruk / strikt een tijdelijke oplossing.
Zie ook het basisvoorbeeld
in de handleiding, en voor meer voor- en nadelen:
- Wat is outputbuffering?
- Waarom outputbuffering gebruiken in PHP?
- Is het gebruik van outputbuffering een slechte gewoonte?
- Gebruik case voor output buffering als de juiste oplossing voor “headers reeds verzonden”
Maar het werkte op de andere server!?
Als je de headers-waarschuwing niet eerder hebt gekregen, dan is de outputbuffering
php.ini-instelling
is veranderd. Het is waarschijnlijk niet geconfigureerd op de huidige/nieuwe server.
Controleren met headers_sent()
Je kunt altijd headers_sent()
gebruiken om te onderzoeken of
het is nog steeds mogelijk om… headers te verzenden. Wat handig is om voorwaardelijk af te drukken
info of andere fallback-logica toepassen.
if (headers_sent()) {
die("Redirect failed. Please click on this link: <a href=...>");
}
else{
exit(header("Location: /user.php"));
}
Handige noodoplossingen zijn:
-
HTML
<meta>
-tagAls uw toepassing structureel moeilijk te repareren is, is een eenvoudige (maar
enigszins onprofessionele) manier om omleidingen toe te staan is het injecteren van een HTML
<meta>
-tag. Een omleiding kan worden bereikt met:<meta http-equiv="Location" content="http://example.com/">
Of met een korte vertraging:
<meta http-equiv="Refresh" content="2; url=../target.html">
Dit leidt tot ongeldige HTML bij gebruik voorbij de sectie
<head>
.
De meeste browsers accepteren het nog steeds. -
JavaScript-omleiding
Als alternatief een JavaScript-omleiding
kan worden gebruikt voor pagina-omleidingen:<script> location.replace("target.html"); </script>
Hoewel dit vaak meer HTML-compatibel is dan de
<meta>
-oplossing,
het is afhankelijk van JavaScript-compatibele clients.
Beide benaderingen maken echter acceptabele fallbacks wanneer echte HTTP-header()
oproepen mislukken. Idealiter combineer je dit altijd met een gebruiksvriendelijke boodschap en
klikbare link als laatste redmiddel. (Dat is bijvoorbeeld wat de http_redirect()
PECL-extensie wel.)
Waarom setcookie()
en session_start()
ook worden beïnvloed
Zowel setcookie()
als session_start()
moeten een Set-Cookie:
HTTP-header verzenden.
Daarom gelden dezelfde voorwaarden en worden vergelijkbare foutmeldingen gegenereerd
voor voortijdige outputsituaties.
(Natuurlijk worden ze ook beïnvloed door uitgeschakelde cookies in de browser
of zelfs proxy-problemen. De sessiefunctionaliteit is uiteraard ook afhankelijk van gratis
schijfruimte en andere php.ini-instellingen, enz.)
Verdere links
- Google biedt een lange lijst met vergelijkbare discussies.
- En natuurlijk zijn veel specifieke gevallenook behandeld op Stack Overflow .
- De WordPress FAQ legt Hoe los ik het probleem met de waarschuwing Headers al op?in een generieke manier.
- Adobe Community: PHP-ontwikkeling: waarom omleidingen niet werken (headers al verzonden )
- Veelgestelde vragen over Nucleus: Wat betekent “paginakopteksten al verzonden”?
- Een van de uitgebreidere uitleg is HTTP-headers en de PHP-header()-functie – Een zelfstudie door NicholasSolutions(link naar internetarchief).
Het behandelt HTTP in detail en geeft een paar richtlijnen voor het herschrijven van scripts.
Antwoord 2, autoriteit 7%
Deze foutmelding wordt geactiveerd wanneer ietswordt verzonden voordat u HTTP-headers verzendt (met setcookie
of header
). Veelvoorkomende redenen om iets uit te voeren vóór de HTTP-headers zijn:
-
Onbedoelde witruimte, vaak aan het begin of einde van bestanden, zoals deze:
<?php // Note the space before "<?php" ?>
Om dit te voorkomen, laat je gewoon de afsluitende ?>
weg – het is sowieso niet verplicht.
- Bytevolgordemarkeringenaan het begin van een php-bestand. Onderzoek je php-bestanden met een hex-editor om erachter te komen of dat het geval is. Ze moeten beginnen met de bytes
3F 3C
. U kunt de BOMEF BB BF
veilig verwijderen vanaf het begin van bestanden. - Expliciete uitvoer, zoals aanroepen naar
echo
,printf
,readfile
,passthru
, code voor<?
enz. - Een waarschuwing van php, als de
display_errors
php.ini-eigenschap is ingesteld. In plaats van te crashen op een programmeerfout, repareert php de fout stilletjes en geeft een waarschuwing af. Hoewel u dedisplay_errors
of error_reportingconfiguraties, moet u het probleem liever oplossen.
Veelvoorkomende redenen zijn toegang tot ongedefinieerde elementen van een array (zoals$_POST['input']
zonder gebruik te maken vanempty
ofisset
om te testen of de invoer is ingesteld), of door een ongedefinieerde constante te gebruiken in plaats van een letterlijke tekenreeks (zoals in$_POST[input]
, let op de ontbrekende aanhalingstekens).
Als u outputbufferinginschakelt, zou het probleem moeten verdwijnen; alle uitvoer na de aanroep naar ob_start
wordt in het geheugen gebufferd totdat u de buffer vrijgeeft, b.v. met ob_end_flush
.
Hoewel uitvoerbuffering de problemen vermijdt, moet u echt bepalen waarom uw toepassing een HTTP-body uitvoert vóór de HTTP-header. Dat zou hetzelfde zijn als een telefoontje plegen en uw dag en het weer bespreken voordat u de beller vertelt dat hij het verkeerde nummer heeft.
Antwoord 3, autoriteit 4%
Ik kreeg deze fout al vele malen eerder, en ik ben er zeker van dat alle PHP-programmeurs deze fout minstens één keer eerder hebben gehad.
Mogelijke oplossing 1
Deze fout kan zijn veroorzaakt door de lege spaties vóórhet begin van het bestand of nahet einde van het bestand. Deze spaties horen hier niet te staan.
ex)
ER MOETEN HIER GEEN LEGE RUIMTEN ZIJN
echo "your code here";
?>
THERE SHOULD BE NO BLANK SPACES HERE
Controleer alle bestanden die zijn gekoppeld aan het bestand dat deze fout veroorzaakt.
Opmerking:Soms voegt EDITOR(IDE) zoals gedit (een standaard linux-editor) een lege regel toe aan het opslagbestand. Dit mag niet gebeuren. Als u Linux gebruikt. je kunt de VI-editor gebruiken om spatie/regels te verwijderen na ?> aan het einde van de pagina.
Mogelijke oplossing 2:
Als dit niet jouw geval is, gebruik dan ob_startom buffering uit te voeren:
<?php
ob_start();
// code
ob_end_flush();
?>
Hierdoor wordt uitvoerbuffering ingeschakeld en worden uw kopteksten gemaakt nadat de pagina is gebufferd.
Antwoord 4, autoriteit 3%
In plaats van de onderstaande regel
//header("Location:".ADMIN_URL."/index.php");
schrijf
echo("<script>location.href = '".ADMIN_URL."/index.php?msg=$msg';</script>");
of
?><script><?php echo("location.href = '".ADMIN_URL."/index.php?msg=$msg';");?></script><?php
Het zal je probleem zeker oplossen.
Ik had hetzelfde probleem, maar ik heb het opgelost door de locatie van de koptekst op de bovenstaande manier te schrijven.
Antwoord 5
Je doet
printf ("Hi %s,</br />", $name);
voordat u de cookies instelt, wat niet is toegestaan. U kunt geen uitvoer vóór de kopteksten verzenden, zelfs geen lege regel.
Antwoord 6
VOORKOMENDE PROBLEMEN:
(gekopieerd van: bron)
====================
1)er mag geen uitvoer (dwz echo..
of HTML-codes) vóór de header(.......);
commando.
2)verwijder alle witruimte(of nieuwe regel) voor <?php
en na ?>
-tags.
3)GOUDEN REGEL!– controleer of dat php-bestand (en ook, als u include
andere bestanden) UTF8 heeft zonder stuklijst-codering (en niet alleen UTF-8). Dat is in veel gevallen een probleem (omdat het UTF8-gecodeerde bestand iets speciaals heeft aan het begin van het php-bestand, wat je teksteditor niet laat zien)!!!!!!!!!!!
4)Na header(...);
moet je exit;
gebruiken
5)gebruik altijd 301 of 302 referentie:
header("location: http://example.com", true, 301 ); exit;
6)Schakel foutrapportage in en zoek de fout.Uw fout kan worden veroorzaakt door een functie die niet werkt. Wanneer u foutrapportage inschakelt, moet u de meest voorkomende fout altijd eerst oplossen. Het kan bijvoorbeeld zijn “Waarschuwing: date_default_timezone_get(): Het is niet veilig om te vertrouwen op de tijdzone-instellingen van het systeem.” – verderop ziet u mogelijk de foutmelding “headers not sent”. Na het oplossen van de bovenste (1e) fout, laadt u uw pagina opnieuw. Als je nog steeds fouten hebt, corrigeer dan opnieuw de bovenste fout.
7)Als geen van bovenstaande helpt, gebruik dan JAVSCRIPT-omleiding (echter sterk niet-aanbevolen methode), misschien de laatste kans in aangepaste gevallen…:
echo "<script type='text/javascript'>window.top.location='http://website.com/';</script>"; exit;
Antwoord 7
Het komt door deze regel:
printf ("Hi %s,</br />", $name);
Je mag niets afdrukken/echovoordat je de headers verzendt.
Antwoord 8
Een simpele tip: Een simpele spatie (of onzichtbaar speciaal teken) in je script, vlak voor de allereerste <?php
tag, kan dit veroorzaken!
Vooral als je in een team werkt en iemand een “zwakke” IDE gebruikt of met vreemde teksteditors in de bestanden heeft gerommeld.
Ik heb deze dingen gezien 😉
Antwoord 9
Een andere slechte gewoonte kan dit probleem veroorzaken, dat nog niet is vermeld.
Bekijk dit codefragment:
<?php
include('a_important_file.php'); //really really really bad practise
header("Location:A location");
?>
Alles is in orde, toch?
Wat als “a_important_file.php” dit is:
<?php
//some php code
//another line of php code
//no line above is generating any output
?>
----------This is the end of the an_important_file-------------------
Dit werkt niet? Waarom?Omdat er al een nieuwe regel wordt gegenereerd.
Hoewel dit geen gebruikelijk scenario is, wat als u een MVC-framework gebruikt dat veel bestanden laadt voordat u dingen aan uw controller overdraagt? Dit is geen ongewoon scenario. Wees hierop voorbereid.
Van PSR-2 2.2 :
- Alle PHP-bestanden MOETEN het
Unix LF (linefeed) line ending
gebruiken. - Alle PHP-bestanden MOETEN eindigen met een
single blank line
. - De afsluiting ?> tag MOET worden
omitted
van bestanden dieonly php
bevatten
Geloof me, het volgen van deze normen kan je heel wat uren van je leven besparen 🙂
Antwoord 10
Soms wanneer het ontwikkelproces zowel WIN-werkstations als LINUX-systemen (hosting) heeft en u in de code geen uitvoer ziet voor de gerelateerde regel, kan dit de opmaak van het bestand zijn en het ontbreken van Unix LF (regelinvoer)
regel einde.
Wat we gewoonlijk doen om dit snel op te lossen, is het bestand hernoemen en op het LINUX-systeem een nieuw bestand maken in plaats van het hernoemde bestand, en dan de inhoud daarin kopiëren. Vaak lost dit het probleem op, omdat sommige van de bestanden die in WIN zijn gemaakt nadat ze naar de hosting zijn verplaatst, dit probleem veroorzaken.
Deze oplossing is een gemakkelijke oplossing voor sites die we via FTP beheren en kan onze nieuwe teamleden soms wat tijd besparen.
Antwoord 11
Over het algemeen treedt deze fout op wanneer we koptekst verzenden na echo of afdrukken. Als deze fout zich voordoet op een specifieke pagina, zorg er dan voor dat die pagina niets weergeeft voordat u start_session()
aanroept.
Voorbeeld van onvoorspelbare fout:
<?php //a white-space before <?php also send for output and arise error
session_start();
session_regenerate_id();
//your page content
Nog een voorbeeld:
<?php
includes 'functions.php';
?> <!-- This new line will also arise error -->
<?php
session_start();
session_regenerate_id();
//your page content
Conclusie: voer geen teken uit voordat u de functies session_start()
of header()
aanroept, zelfs geen witruimte of nieuwe regel