W3docs

__halt_compiler()

In questo articolo ci concentriamo sul costrutto __halt_compiler() di PHP: panoramica, funzionamento ed esempi d'uso.

In questo articolo ci concentriamo sul costrutto linguistico __halt_compiler() di PHP. Forniremo una panoramica del costrutto, il suo funzionamento e degli esempi d'uso.

Introduzione al costrutto __halt_compiler()

Il costrutto linguistico __halt_compiler() è una caratteristica unica e potente di PHP. Permette di incorporare dati direttamente nel codice PHP. Questi dati possono essere di qualsiasi tipo, inclusi testo, dati binari o persino un intero script.

Quando l'interprete PHP incontra il costrutto __halt_compiler() nel codice, ferma il parser PHP e tratta tutto ciò che segue la chiamata come dati grezzi. Questo significa che è possibile incorporare qualsiasi tipo di dato nel codice e accedervi in seguito come stringa o dato binario.

__halt_compiler() è un costrutto linguistico, non una funzione ordinaria, quindi si invoca senza argomenti e non restituisce un valore. Viene usato più spesso per costruire strumenti in un singolo file in cui codice e dati vengono distribuiti insieme — ad esempio archivi auto-estraenti (il formato PHAR di PHP utilizza esattamente questa tecnica) o programmi di installazione che includono il proprio payload.

Come usare il costrutto __halt_compiler()

Il costrutto __halt_compiler() è molto semplice da usare. Basta invocarlo nel codice PHP, seguito dai dati che si desidera incorporare. Ecco un esempio:

Come usare il costrutto __halt_compiler()?

php— editable, runs on the server

In questo esempio abbiamo un semplice script PHP che stampa del testo usando il costrutto echo. Chiamiamo poi il costrutto __halt_compiler() e incorporiamo alcuni dati grezzi dopo di esso. Quando l'interprete PHP incontra il costrutto __halt_compiler(), ferma il parser e tratta tutto ciò che segue come dati grezzi.

Accedere ai dati incorporati con __COMPILER_HALT_OFFSET__

Quando un file contiene __halt_compiler(), PHP definisce una costante speciale, __COMPILER_HALT_OFFSET__, che contiene la posizione in byte del primo carattere dopo la chiamata. Questo è il metodo canonico e più veloce per leggere il payload incorporato dallo stesso file — non è necessario cercare manualmente un marcatore nel file.

Lettura dei dati incorporati dallo stesso file

<?php
// File: bundle.php
echo "Reading the embedded payload...\n";

// Open this very file and jump straight to the data.
$fp = fopen(__FILE__, 'rb');
fseek($fp, __COMPILER_HALT_OFFSET__);
$data = stream_get_contents($fp);
fclose($fp);

echo $data;

__halt_compiler();
Hello from the embedded data!

Qui __COMPILER_HALT_OFFSET__ punta al byte immediatamente dopo __halt_compiler();, quindi ci posizioniamo su di esso e leggiamo tutto ciò che segue come payload grezzo. La costante esiste solo in un file che contiene effettivamente il costrutto.

Accedere ai dati incorporati da un altro file

Se hai bisogno di leggere il payload da un file diverso, la __COMPILER_HALT_OFFSET__ di quel file non è disponibile, quindi devi individuare manualmente il marcatore con strpos() ed estrarre i dati con substr() dopo averlo caricato tramite file_get_contents().

Ecco un esempio di come leggere i dati incorporati da uno script separato:

Accedere ai dati incorporati in PHP

<?php
// File: embed.php
echo "This is some PHP code.";
__halt_compiler();
This is some raw data.
?>
<?php
// File: extract.php
// Read the script file and extract the data
$content = file_get_contents('embed.php');
$pos = strpos($content, '__halt_compiler();');
if ($pos !== false) {
    $offset = $pos + strlen('__halt_compiler();');
    $data = substr($content, $offset);
    echo $data;
}
?>

In questo esempio, creiamo prima un file con dati incorporati. Utilizziamo poi uno script separato per leggere il file originale ed estrarne i dati individuando il marcatore __halt_compiler(); e calcolando l'offset. Infine, stampiamo i dati estratti usando il costrutto echo.

Nota: La costante __COMPILER_HALT_OFFSET__ è definita solo all'interno del file che contiene effettivamente __halt_compiler(). Quando si legge un file diverso, strpos() restituisce false se il marcatore è assente, quindi verifica sempre la posizione con un controllo !== false prima di calcolare l'offset.

Limitazioni e avvertenze

Tieni a mente queste regole quando utilizzi __halt_compiler():

  • Deve essere chiamato al livello superiore di un file. Non può essere inserito all'interno di una funzione, un metodo, un condizionale, un ciclo o qualsiasi altro blocco. Farlo provoca un errore fatale.
  • Una sola volta per file. Un file può contenere __halt_compiler() una sola volta — segna un unico punto di interruzione.
  • Tutto ciò che segue viene ignorato come codice. Il tag di chiusura ?> (se presente) e qualsiasi cosa dopo la chiamata vengono trattati come byte grezzi, mai analizzati. Per questo motivo di solito si omette il ?> finale e si lascia seguire direttamente i dati.
  • Non è una funzione. Non si può prenderne l'indirizzo, passarla come callback o chiamarla dinamicamente.

Conclusione

In conclusione, il costrutto linguistico __halt_compiler() è una caratteristica potente e flessibile di PHP che consente di incorporare dati direttamente nel codice. Comprendendo come funziona il costrutto e come accedere ai dati incorporati, è possibile sfruttare questa funzionalità per creare script PHP più potenti e flessibili. I casi d'uso pratici comuni includono archivi auto-estraenti, raggruppamento di asset statici (come CSS o JavaScript) con logica PHP e creazione di applicazioni PHP in un singolo file. Se hai principalmente bisogno di includere codice da altri file anziché incorporare dati grezzi, consulta invece include.

Esercizio

Pratica
Che cos'è la funzione '__halt_compiler' in PHP?
Che cos'è la funzione '__halt_compiler' in PHP?
Was this page helpful?