W3docs

__halt_compiler()

In diesem Artikel befassen wir uns mit dem PHP-Sprachkonstrukt __halt_compiler(): Funktionsweise, Verwendung und praktische Beispiele.

In diesem Artikel befassen wir uns mit dem PHP-Sprachkonstrukt __halt_compiler(). Wir geben Ihnen einen Überblick über das Konstrukt, wie es funktioniert, und Beispiele für seinen Einsatz.

Einführung in das __halt_compiler()-Konstrukt

Das Sprachkonstrukt __halt_compiler() ist eine einzigartige und leistungsfähige Funktion von PHP. Es erlaubt Ihnen, Daten direkt in Ihren PHP-Code einzubetten. Diese Daten können beliebiger Art sein, darunter Text, Binärdaten oder sogar ein vollständiges Skript.

Wenn der PHP-Interpreter auf das __halt_compiler()-Konstrukt in Ihrem Code stößt, hält er den PHP-Parser an und behandelt alles nach dem Aufruf als Rohdaten. Das bedeutet, dass Sie jede Art von Daten in Ihren Code einbetten und später als Zeichenkette oder Binärdaten darauf zugreifen können.

__halt_compiler() ist ein Sprachkonstrukt, keine reguläre Funktion. Sie rufen es daher ohne Argumente auf, und es gibt keinen Wert zurück. Es wird am häufigsten verwendet, um Einzeldatei-Werkzeuge zu erstellen, bei denen Code und Daten zusammen geliefert werden – zum Beispiel selbstextrahierende Archive (PHPs PHAR-Format nutzt genau diese Technik) oder Installer, die ihren eigenen Payload mitbringen.

Verwendung des __halt_compiler()-Konstrukts

Das __halt_compiler()-Konstrukt ist sehr einfach zu verwenden. Rufen Sie es in Ihrem PHP-Code auf, gefolgt von den Daten, die Sie einbetten möchten. Hier ist ein Beispiel:

Wie verwendet man das __halt_compiler()-Konstrukt?

php— editable, runs on the server

In diesem Beispiel haben wir ein einfaches PHP-Skript, das mit dem echo-Konstrukt Text ausgibt. Wir rufen dann das __halt_compiler()-Konstrukt auf und betten danach einige Rohdaten ein. Wenn der PHP-Interpreter auf das __halt_compiler()-Konstrukt trifft, hält er den Parser an und behandelt alles danach als Rohdaten.

Zugriff auf die eingebetteten Daten mit __COMPILER_HALT_OFFSET__

Wenn eine Datei __halt_compiler() enthält, definiert PHP eine spezielle Konstante, __COMPILER_HALT_OFFSET__, die die Byteposition des ersten Zeichens nach dem Aufruf speichert. Dies ist der kanonische und schnellste Weg, den eingebetteten Payload aus derselben Datei heraus zu lesen – Sie müssen die Datei nicht selbst nach einem Marker durchsuchen.

Eingebettete Daten aus derselben Datei lesen

<?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!

Hier zeigt __COMPILER_HALT_OFFSET__ auf das Byte direkt nach __halt_compiler();, sodass wir dorthin springen und alles Folgende als rohen Payload lesen. Die Konstante existiert nur in einer Datei, die das Konstrukt tatsächlich enthält.

Zugriff auf die eingebetteten Daten aus einer anderen Datei

Wenn Sie den Payload aus einer anderen Datei lesen müssen, steht Ihnen deren __COMPILER_HALT_OFFSET__ nicht zur Verfügung. Daher suchen Sie den Marker manuell mit strpos() und extrahieren die Daten mit substr(), nachdem Sie die Datei via file_get_contents() geladen haben.

Hier ist ein Beispiel, wie Sie die eingebetteten Daten aus einem separaten Skript lesen:

Zugriff auf eingebettete Daten 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 diesem Beispiel erstellen wir zunächst eine Datei mit eingebetteten Daten. Anschließend verwenden wir ein separates Skript, um die ursprüngliche Datei zu lesen und die Daten zu extrahieren, indem wir den __halt_compiler();-Marker lokalisieren und den Offset berechnen. Abschließend geben wir die extrahierten Daten mit dem echo-Konstrukt aus.

Hinweis: Die Konstante __COMPILER_HALT_OFFSET__ ist nur innerhalb der Datei definiert, die __halt_compiler() tatsächlich enthält. Beim Lesen einer anderen Datei gibt strpos() false zurück, wenn der Marker fehlt. Überprüfen Sie die Position daher immer mit einem !== false-Check, bevor Sie den Offset berechnen.

Einschränkungen und Besonderheiten

Beachten Sie diese Regeln bei der Verwendung von __halt_compiler():

  • Es muss auf der obersten Ebene einer Datei aufgerufen werden. Sie können es nicht innerhalb einer Funktion, Methode, Bedingung, Schleife oder einem anderen Block platzieren. Dies führt zu einem fatalen Fehler.
  • Einmal pro Datei. Eine Datei darf __halt_compiler() nur einmal enthalten – es markiert einen einzigen Abschneidepunkt.
  • Alles danach wird als Code ignoriert. Das schließende ?>-Tag (falls vorhanden) und alles nach dem Aufruf werden als rohe Bytes behandelt und niemals geparst. Daher lässt man das abschließende ?> üblicherweise weg und lässt die Daten direkt folgen.
  • Es ist keine Funktion. Sie können seine Adresse nicht nehmen, es nicht als Callback übergeben oder dynamisch aufrufen.

Fazit

Zusammenfassend lässt sich sagen, dass das Sprachkonstrukt __halt_compiler() ein leistungsfähiges und flexibles Feature von PHP ist, das es Ihnen erlaubt, Daten direkt in Ihren Code einzubetten. Wenn Sie verstehen, wie das Konstrukt funktioniert und wie Sie auf die eingebetteten Daten zugreifen, können Sie dieses Feature nutzen, um leistungsfähigere und flexiblere PHP-Skripte zu erstellen. Typische praktische Anwendungsfälle sind selbstextrahierende Archive, das Bündeln statischer Ressourcen (wie CSS oder JavaScript) mit PHP-Logik und die Erstellung von PHP-Einzeldatei-Anwendungen. Wenn Sie hauptsächlich Code aus anderen Dateien einbinden möchten, anstatt Rohdaten einzubetten, sehen Sie sich stattdessen include an.

Übungen

Übung
Was ist das '__halt_compiler'-Konstrukt in PHP?
Was ist das '__halt_compiler'-Konstrukt in PHP?
Was this page helpful?