getTraceAsString()
Scopri il metodo PHP getTraceAsString(): come restituisce lo stack trace di un'eccezione come stringa, come leggere l'output e come registrarlo.
Cosa fa getTraceAsString()
getTraceAsString() è un metodo disponibile su ogni eccezione PHP (qualsiasi classe che
implementa Throwable — Exception, Error e le loro sottoclassi). Restituisce lo
stack trace — la catena di chiamate a funzioni e metodi attive nel momento in cui è stata
lanciata l'eccezione — formattato come un'unica stringa leggibile dall'utente.
Lo stack trace risponde alla domanda "come ci siamo arrivati?" Quando qualcosa viene lanciato
in profondità nel codice, il messaggio da solo (getMessage()) dice cosa è andato storto, ma
il trace indica il percorso esatto di chiamate che vi ha condotto. Questo lo rende il dato più
utile in assoluto durante il debug di un errore difficile da riprodurre.
getTraceAsString() è la versione stringa di getTrace(), che
restituisce le stesse informazioni come array strutturato. Usa getTrace() quando devi
ispezionare i singoli frame in modo programmatico; usa getTraceAsString() quando vuoi
semplicemente qualcosa da registrare o stampare.
Sintassi
public Throwable::getTraceAsString(): stringNon accetta argomenti ed è final nelle classi base Exception e Error, quindi
restituisce sempre il formato di trace standard di PHP. Si chiama su un oggetto eccezione
catturato all'interno di un blocco catch:
<?php
try {
// Code that may throw an exception
} catch (Throwable $e) {
$trace = $e->getTraceAsString();
}Catturare Throwable (invece di solo Exception) significa gestire anche gli oggetti Error
come TypeError e DivisionByZeroError. Vedi il capitolo Exception
per la gerarchia completa.
Un Esempio Completo ed Eseguibile
Questo script lancia un'eccezione a due livelli di profondità così puoi vedere come appare effettivamente la stringa del trace:
<?php
function loadUser(int $id): array
{
throw new InvalidArgumentException("No user with id $id");
}
function handleRequest(): void
{
loadUser(42);
}
try {
handleRequest();
} catch (Throwable $e) {
echo $e->getTraceAsString();
}Output:
#0 /app/index.php(10): loadUser(42)
#1 /app/index.php(14): handleRequest()
#2 {main}Leggere l'Output
Ogni riga è un frame nello stack delle chiamate, elencato dal più interno al più esterno:
#0,#1, … — il numero del frame.#0è la chiamata in esecuzione quando è stata lanciata l'eccezione; i numeri più alti sono i chiamanti sopra di essa./app/index.php(10)— il file e il numero di riga del sito di chiamata.loadUser(42)— la funzione o il metodo chiamato, con i suoi argomenti. Gli argomenti stringa lunghi vengono troncati (es.'/etc/app/missin...') per mantenere leggibile il trace.#2 {main}— il frame finale speciale che segna lo script di livello superiore (lo scope globale).
Il punto del lancio stesso (il file e la riga esatti dove è stato eseguito throw) non è in
questa stringa — si trova in getFile() e getLine().
Esempi
Esempio 1: Registrare il Trace su un File
In produzione raramente vuoi mostrare un trace all'utente — lo registri per un'analisi successiva. Combina il messaggio, il file e la riga con il trace per un record completo:
<?php
try {
// Code that may throw an exception
} catch (Throwable $e) {
$entry = sprintf(
"[%s] %s in %s:%d\n%s\n\n",
date('Y-m-d H:i:s'),
$e->getMessage(),
$e->getFile(),
$e->getLine(),
$e->getTraceAsString()
);
file_put_contents('/path/to/app.log', $entry, FILE_APPEND | LOCK_EX);
}LOCK_EX impedisce a due richieste simultanee di interlacciare le loro voci di log. Per
applicazioni reali è preferibile una libreria di logging come Monolog, ma i dati sottostanti
sono la stessa stringa che ottieni qui.
Esempio 2: Visualizzare il Trace nel Browser (Solo in Sviluppo)
Quando si lavora in locale può essere comodo stampare il trace direttamente sulla pagina.
Racchiudilo in <pre> per preservare le interruzioni di riga ed eseguine l'escape per evitare
che il contenuto del trace inietti HTML:
<?php
try {
// Code that may throw an exception
} catch (Throwable $e) {
echo '<pre>' . htmlspecialchars($e->getTraceAsString()) . '</pre>';
}Non esporre mai i trace agli utenti finali in produzione — rivelano percorsi di file, struttura del codice e talvolta valori degli argomenti che aiutano gli attaccanti. Proteggilo con un controllo sull'ambiente.
Esempio 3: Preservare il Trace Attraverso i Re-throw
Quando catturi un'eccezione di basso livello e la rilanci come una più significativa, passa l'originale come eccezione precedente per non perdere il suo trace:
<?php
try {
// some database call that throws PDOException
} catch (PDOException $e) {
throw new RuntimeException('Could not load the report', 0, $e);
}La nuova RuntimeException ha il proprio trace, mentre
getPrevious() ti restituisce l'eccezione originale (e il suo
getTraceAsString()). Il gestore delle eccezioni non catturate predefinito di PHP stampa
entrambe, concatenate.
Errori Comuni
- Il trace descrive il punto del lancio, non il punto del catch. È fissato nel momento in
cui l'eccezione viene costruita, quindi chiamare
getTraceAsString()in seguito mostra ancora dove ha avuto origine l'eccezione, non dove è stata gestita. - Gli argomenti possono essere troncati o nascosti. Le stringhe lunghe vengono abbreviate;
con l'impostazione INI
zend.exception_ignore_argsabilitata (predefinita in molte configurazioni di produzione), i valori degli argomenti vengono omessi completamente per ragioni di sicurezza. - Restituisce una stringa, mai
null. Anche per un'eccezione lanciata al livello superiore si ottiene almeno il frame#0 {main}.
Metodi Correlati
getTrace()— gli stessi dati come array strutturato.getMessage()— il messaggio di errore leggibile dall'utente.getCode()— il codice numerico dell'eccezione.getPrevious()— l'eccezione precedente concatenata.set-exception-handler()— gestire le eccezioni non catturate globalmente.
Conclusione
getTraceAsString() trasforma lo stack delle chiamate di un'eccezione in una stringa compatta
e registrabile, rendendolo uno degli strumenti più preziosi per diagnosticare gli errori in PHP.
Abbinalo a getMessage(), getFile() e getLine() per catturare un quadro completo di ogni
errore, registralo invece di mostrarlo agli utenti in produzione e preserva la catena con
getPrevious() ogni volta che esegui un re-throw.