Hoe de fout ‘Headers al verzonden’ in PHP op te lossen

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:

  • Opzettelijk:

    • print, echoen andere functies die output produceren
    • Onbewerkte <html>secties voorafgaand aan <?phpcode.

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:

  1. Afdrukken, echo

    Opzettelijke uitvoer van print– en echo-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 dat header()-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.

  2. Onbewerkte HTML-gebieden

    Ongeparseerde HTML-secties in een .php-bestand worden ook direct uitgevoerd.
    Scriptvoorwaarden die een header()-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.
  3. Witruimte voor <?phpvoor “script.php regel 1” waarschuwingen

    Als 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.

  4. 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 bytereeks EF 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 tekens i»?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:

    joes-editor met UTF-8 BOM-plaatsaanduiding en MC-editor een punt

    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 is hexdumpmeestal beschikbaar,
    zo niet een grafische variant die het controleren van deze en andere problemen vereenvoudigt:

    beav hexeditor toont utf-8 bom

    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/awkof recode).
    Specifiek voor PHP is er de phptagstag 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.

  5. 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 zijn include()d-scripts de boosdoener.)

  6. 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 gzipstream-coderingsinstelling
      of de ob_gzhandler.
    • Maar het kan ook een dubbel geladen extension=module zijn
      het genereren van een impliciet PHP-opstart-/waarschuwingsbericht.

  7. 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_reportingof display_errorshebt 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.

  1. 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.

  2. 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. (Vereist ob_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:

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>-tag

    Als 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


Antwoord 2, autoriteit 7%

Deze foutmelding wordt geactiveerd wanneer ietswordt verzonden voordat u HTTP-headers verzendt (met setcookieof 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 BOM EF BB BFveilig 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_errorsphp.ini-eigenschap is ingesteld. In plaats van te crashen op een programmeerfout, repareert php de fout stilletjes en geeft een waarschuwing af. Hoewel u de display_errorsof 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 van emptyof issetom 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_startwordt 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 <?phpen na ?>-tags.

3)GOUDEN REGEL!– controleer of dat php-bestand (en ook, als u includeandere 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 <?phptag, 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 endinggebruiken.
  • Alle PHP-bestanden MOETEN eindigen met een single blank line.
  • De afsluiting ?> tag MOET worden omittedvan bestanden die only 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

Other episodes