Funzione PHP headers_sent(): tutto quello che devi sapere
Come sviluppatore PHP, potresti dover verificare se gli header HTTP sono già stati inviati al client. headers_sent() è una funzione built-in di PHP.
Ogni risposta HTTP è divisa in due parti: un blocco di header (codice di stato, Content-Type, cookie, redirect) seguito dal corpo della risposta. Il problema è che gli header devono essere inviati prima di qualsiasi output nel corpo. Nel momento in cui PHP emette un singolo byte nel corpo, scarica gli header e li blocca — qualsiasi chiamata successiva a header(), setcookie() o session_start() genera il famigerato avviso Cannot modify header information - headers already sent.
headers_sent() è la funzione built-in che ti permette di verificare, prima di tentare di inviare un header, se è già troppo tardi. Questa guida ne descrive la sintassi, i parametri per riferimento, le cause dell'output prematuro e come risolverle.
Cosa fa headers_sent()
headers_sent() restituisce un valore boolean:
true— gli header sono già stati inviati (l'output è iniziato). Qualsiasi ulteriore chiamata aheader()/setcookie()fallirà.false— nessun output è ancora iniziato, quindi è ancora sicuro impostare gli header.
Proteggere la logica degli header con headers_sent() ti consente di evitare l'avviso e gestire la situazione in modo elegante (ad esempio, registrando il problema o ricorrendo a un redirect JavaScript) invece di bloccare la pagina.
Sintassi
headers_sent(string &$filename = null, int &$line = null): boolEntrambi i parametri sono facoltativi e passati per riferimento. Quando gli header sono stati inviati, PHP li compila con la posizione dell'output che li ha causati:
$filename— il nome del file sorgente in cui l'output è iniziato.$line— il numero di riga all'interno di quel file.
Questo è ciò che rende headers_sent() così utile per il debug: ti indica direttamente il punto incriminato.
Utilizzo di base
Controlla il valore restituito prima di inviare un header:
<?php
if (!headers_sent()) {
header('Location: /dashboard');
exit;
}
echo 'Headers were already sent, cannot redirect via HTTP.';Se l'output non è ancora iniziato, viene inviato l'header di redirect. In caso contrario, lo script evita l'avviso fatale e stampa un messaggio di fallback.
Trovare dove è iniziato l'output
Passa le due variabili per riferimento per scoprire esattamente cosa ha inviato gli header — fondamentale quando uno spazio o un echo indesiderato è nascosto in un file incluso:
<?php
if (headers_sent($file, $line)) {
echo "Headers already sent in $file on line $line";
} else {
setcookie('theme', 'dark');
echo 'Cookie set successfully.';
}Se la condizione è vera, si ottiene un messaggio come Headers already sent in /var/www/header.php on line 12, che indica con precisione dove cercare.
Cosa causa "Headers Already Sent"
Qualsiasi cosa produca output nel corpo prima della chiamata all'header scarica gli header. Cause comuni:
- Spazi bianchi o una riga vuota prima di
<?php— anche uno spazio o un a capo conta come output. - Un a capo dopo il tag di chiusura
?>di un file incluso. (Buona pratica: omettere il tag di chiusura?>nei file puramente PHP.) echo,print,printfovar_dumpeseguiti prima dell'header.- Un file UTF-8 salvato con BOM (byte-order mark) — quei byte iniziali invisibili sono output.
- Avvisi/notice PHP stampati sulla pagina (quando
display_errorsè attivo) prima degli header.
Correggere con il buffer di output
Se non puoi riordinare il codice in modo che tutti gli header vengano prima, racchiudi lo script in un buffer di output. ob_start() mantiene il corpo in memoria invece di inviarlo immediatamente, così gli header rimangono modificabili fino allo svuotamento del buffer:
<?php
ob_start(); // start buffering — nothing is sent yet
echo 'Some early output';
// Still safe: the echo above is held in the buffer, headers are not sent
setcookie('user', 'jane');
header('X-App-Version: 2.0');
ob_end_flush(); // now send headers, then the buffered bodyPoiché l'output è nel buffer, headers_sent() restituirebbe ancora false dopo l'echo, e le successive chiamate a setcookie() e header() avranno successo.
Funzioni correlate
header()— invia un header HTTP grezzo.headers_list()— elenca gli header in coda o già inviati.setcookie()— imposta un cookie (invia un headerSet-Cookie).ob_start()— avvia il buffer di output per ritardare l'invio degli header.- PHP Sessions —
session_start()invia anch'essa header ed è un trigger frequente.
Conclusione
headers_sent() è una guardia piccola ma essenziale: chiamala prima di qualsiasi header(), setcookie() o session_start() per verificare se l'output è già iniziato. Quando restituisce true, gli argomenti per riferimento $filename e $line individuano l'output incriminato così puoi correggerlo — oppure racchiudi lo script in ob_start() per mantenere gli header modificabili fino a quando sei pronto a svuotare il buffer.