Heim >Backend-Entwicklung >PHP-Tutorial >Wie PHP ausführt - vom Quellcode zum Rendern

Wie PHP ausführt - vom Quellcode zum Rendern

Jennifer Aniston
Jennifer AnistonOriginal
2025-02-10 10:11:11818Durchsuche

Wie PHP ausführt - vom Quellcode zum Rendern

Dieser Artikel wurde von Younes Rafie geprüft. Vielen Dank an alle Peer -Rezensenten von SitePoint, die SitePoint -Inhalte so gut wie möglich gemacht haben!


Inspiriert von einem kürzlich durchgeführten Artikel darüber, wie Ruby Code ausgeführt wird, deckt dieser Artikel den Ausführungsprozess für PHP -Code ab.

Wie PHP ausführt - vom Quellcode zum Rendern

Key Takeaways

  • PHP -Codeausführung umfasst vier Stufen: Lexing, Parsen, Zusammenstellung und Interpretation. Jede Stufe ist entscheidend beim Konvertieren von PHP-Quellcode in maschinelles Lesbarer Code.
  • Lexing oder Tokens ist der Prozess, einen String (PHP -Quellcode) in eine Sequenz von Token zu verwandeln. Jedes Token ist ein benannter Kenner für den Wert, den er übereinstimmte. Diese Phase speichert auch das Lexeme und die Zeilennummer des übereinstimmten Tokens.
  • Die Parsing -Stufe überprüft die Gültigkeit der Token -Ordnung und erzeugt den abstrakten Syntaxbaum (AST). Der AST ist eine Baumansicht des Quellcodes, die während der Kompilierungsphase verwendet werden.
  • Die Kompilierungsphase emittiert Opcodes, indem sie das AST durchqueren und Optimierungen wie Auflösungsaufrufe mit buchstäblichen Argumenten und faltungsübergreifenden mathematischen Ausdrücken durchführen. Die Ausgabe dieser Phase kann mit Opcache, VLD und PHPDBG geprüft werden.
  • Die Interpretationsphase ist die letzte Phase, in der die Opcodes auf dem Zend Engine (ZE) VM ausgeführt werden. Die Ausgabe dieser Phase ist das, was Ihr PHP -Skript über Befehle wie Echo, Druck, var_dump usw. ausgibt.

Einführung

, wenn wir ein Stück PHP -Code ausführen, ist viel los. Im Großen und Ganzen durchläuft der PHP -Interpreter vier Stufen, wenn der Code ausgeführt wird:

  1. Lexing
  2. Parsing
  3. Compilation
  4. Interpretation

Dieser Artikel wird durch diese Phasen überfliegen und zeigen, wie wir die Ausgabe aus jeder Phase anzeigen können, um wirklich zu sehen, was los ist. Beachten Sie, dass einige der verwendeten Erweiterungen bereits Teil Ihrer PHP-Installation sein sollten (z.

Stufe 1 - Lexing

Lexing (oder Tokenisierung) ist der Prozess, einen String (PHP -Quellcode, in diesem Fall) in eine Abfolge von Token zu verwandeln. Ein Token ist einfach eine benannte Kennung für den Wert, den es übereinstimmte. PHP verwendet RE2C, um seinen Lexer aus der Definitionsdatei zend_language_scanner.l zu generieren.

wir können die Ausgabe der Lexingstufe über die Tokenizer -Erweiterung sehen:

$code = <<<'code'
<span><span><?php
</span></span><span><span>$a = 1;
</span></span><span>code<span>;
</span></span><span>
</span><span><span>$tokens = token_get_all($code);
</span></span><span>
</span><span><span>foreach ($tokens as $token) {
</span></span><span>    <span>if (is_array($token)) {
</span></span><span>        <span>echo "Line <span><span>{$token[2]}</span>: "</span>, token_name($token[0]), " ('<span><span>{$token[1]}</span>')"</span>, PHP_EOL;
</span></span><span>    <span>} else {
</span></span><span>        <span>var_dump($token);
</span></span><span>    <span>}
</span></span><span><span>}
</span></span>
Ausgänge:

$code = <<<'code'
<span><span><?php
</span></span><span><span>$a = 1;
</span></span><span>code<span>;
</span></span><span>
</span><span><span>$tokens = token_get_all($code);
</span></span><span>
</span><span><span>foreach ($tokens as $token) {
</span></span><span>    <span>if (is_array($token)) {
</span></span><span>        <span>echo "Line <span><span>{$token[2]}</span>: "</span>, token_name($token[0]), " ('<span><span>{$token[1]}</span>')"</span>, PHP_EOL;
</span></span><span>    <span>} else {
</span></span><span>        <span>var_dump($token);
</span></span><span>    <span>}
</span></span><span><span>}
</span></span>

Es gibt ein paar bemerkenswerte Punkte aus der obigen Ausgabe. Der erste Punkt ist, dass nicht alle Teile des Quellcodes als Token bezeichnet werden. Stattdessen werden einige Symbole an und für sich als Token angesehen (wie z. B. =,;,:,? Usw.). Der zweite Punkt ist, dass der Lexer tatsächlich etwas mehr tut, als nur einen Tokenstrom auszugeben. In den meisten Fällen speichert es auch das Lexem (der vom Token übereinstimmende Wert) und die Zeilennummer des übereinstimmenden Tokens (der für Stapelspuren verwendet wird).

Stufe 2 - Parsing

Der Parser wird ebenfalls generiert, diesmal mit Bison über eine BNF -Grammatikdatei. PHP verwendet eine kontextfreie Grammatik von LALR (1) (nach vorne, links nach rechts). Der Aussichtsteil bedeutet einfach, dass der Parser in der Lage ist, N -Token (1, in diesem Fall) voranzutreiben, um Unklarheiten zu lösen, auf die er während der Parsen begegnen kann. Der Teil von links nach rechts bedeutet, dass er den Token-Stream von links nach rechts analysiert.

Die erzeugte Parserstufe nimmt den Token -Stream aus dem Lexer als Eingabe und hat zwei Jobs. Es überprüft zunächst die Gültigkeit des Token -Ordens, indem versucht wird, sie gegen eine der in seiner BNF -Grammatikdatei definierten Grammatikregeln zu vereinen. Dies stellt sicher, dass die Token im Token -Strom gültige Sprachkonstrukte gebildet werden. Der zweite Auftrag des Parsers besteht darin, die abstrakte Syntaxbaum (AST) zu generieren - eine Baumansicht des Quellcodes, der während der nächsten Stufe verwendet wird (Zusammenstellung).

Wir können eine Form von den vom Parser erzeugten AST mit der PHP-Ast-Erweiterung anzeigen. Der interne AST ist nicht direkt freigelegt, da es nicht besonders „sauber“ ist, mit (in Bezug auf Konsistenz und allgemeine Benutzerfreundlichkeit) zu arbeiten, und daher führt die PHP-Ast-Erweiterung einige Transformationen durch, um es schöner zu machen, mit zu arbeiten.

Schauen wir uns das AST für ein rudimentäres Stück Code an:

Line 1: T_OPEN_TAG ('<?php
')
Line 2: T_VARIABLE ('$a')
Line 2: T_WHITESPACE (' ')
string(1) "="
Line 2: T_WHITESPACE (' ')
Line 2: T_LNUMBER ('1')
string(1) ";"

Ausgabe:

$code = <<<'code'
<span><span><?php
</span></span><span><span>$a = 1;
</span></span><span>code<span>;
</span></span><span>
</span><span><span>print_r(ast<span>\parse_code</span>($code, 30));
</span></span>

Die Baumknoten (die typischerweise vom Typ Astnode sind) haben mehrere Eigenschaften:

  • Art - ein ganzzahliger Wert, der den Knotentyp darstellt; jeweils hat eine entsprechende Konstante (z.
  • Flags - Eine Ganzzahl, die überlastetes Verhalten angibt (z. B. ein Astast_Binary_OP -Knoten wird Flags haben, um zu unterscheiden, welche Binäroperation auftritt)
  • LINENO - Die Zeilennummer, wie aus den Token -Informationen früher
  • festgestellt wird
  • Kinder - Subknoten, typischerweise Teile des Knotens weiter nach unten (z. B. ein Funktionsknoten haben die Kinder: Parameter, Rückgabetyp, Körper usw.)

Die AST -Ausgabe dieser Phase ist praktisch für Tools wie statische Codeanalysatoren (z. B. Phan).

Stufe 3 - Zusammenstellung

Die Kompilierungsphase verbraucht das AST, wo sie Opcodes durch rekursives Durchqueren des Baumes emittiert. Diese Phase führt auch einige Optimierungen durch. Dazu gehören die Auflösung einiger Funktionsaufrufe mit wörtlichen Argumenten (wie Strlen ("ABC") bis int (3)) und Faltungskonstante mathematische Ausdrücke (wie 60 * 60 * 24 bis int (86400)).

Wir können die Opcode -Ausgabe in dieser Phase in vielerlei Hinsicht inspizieren, einschließlich Opcache, VLD und PHPDBG. Ich werde VLD dafür verwenden, da ich der Meinung bin

Lassen Sie uns sehen, wie die Ausgabe für das folgende Datei -Skript ist:

$code = <<<'code'
<span><span><?php
</span></span><span><span>$a = 1;
</span></span><span>code<span>;
</span></span><span>
</span><span><span>$tokens = token_get_all($code);
</span></span><span>
</span><span><span>foreach ($tokens as $token) {
</span></span><span>    <span>if (is_array($token)) {
</span></span><span>        <span>echo "Line <span><span>{$token[2]}</span>: "</span>, token_name($token[0]), " ('<span><span>{$token[1]}</span>')"</span>, PHP_EOL;
</span></span><span>    <span>} else {
</span></span><span>        <span>var_dump($token);
</span></span><span>    <span>}
</span></span><span><span>}
</span></span>
Ausführen des folgenden Befehls:

Line 1: T_OPEN_TAG ('<?php
')
Line 2: T_VARIABLE ('$a')
Line 2: T_WHITESPACE (' ')
string(1) "="
Line 2: T_WHITESPACE (' ')
Line 2: T_LNUMBER ('1')
string(1) ";"
Unsere Ausgabe ist:

$code = <<<'code'
<span><span><?php
</span></span><span><span>$a = 1;
</span></span><span>code<span>;
</span></span><span>
</span><span><span>print_r(ast<span>\parse_code</span>($code, 30));
</span></span>
Die Opcodes ähneln irgendwie dem ursprünglichen Quellcode, um den Grundvorgängen zu folgen. (Ich werde mich nicht mit den Details von Opcodes in diesem Artikel befassen, da dies mehrere gesamte Artikel an sich annehmen würde.) Auf Opcode -Ebene im obigen Skript wurden keine Optimierungen angewendet - aber wie wir sehen können, können wir die Kompilierungsphase sehen hat einige gemacht, indem er die konstante Bedingung auflöst (php_version === '7.1.0-dev') zu true.

opcache kann mehr als nur Opcodes zwischengespeichern (damit die Lexing-, Parsen- und Kompilierungsstufen umgehen). Es packt auch viele verschiedene Optimierungsstufen mit sich. Lassen Sie uns die Optimierungsstufe auf vier Pässe erheben, um zu sehen, was herauskommt:

Befehl:

ast\Node Object (
    [kind] => 132
    [flags] => 0
    [lineno] => 1
    [children] => Array (
        [0] => ast\Node Object (
            [kind] => 517
            [flags] => 0
            [lineno] => 2
            [children] => Array (
                [var] => ast\Node Object (
                    [kind] => 256
                    [flags] => 0
                    [lineno] => 2
                    [children] => Array (
                        [name] => a
                    )
                )
                [expr] => 1
            )
        )
    )
)
Ausgabe:

<span>if (PHP_VERSION === '7.1.0-dev') {
</span>    <span>echo 'Yay', PHP_EOL;
</span><span>}
</span>
Wir können sehen, dass der konstante Zustand entfernt wurde und die beiden Echo -Anweisungen in eine einzige Anweisung zusammengefasst wurden. Dies sind nur ein Vorgeschmack auf die vielen Optimierungen, die Opcache bei der Ausführung von Passer über die Opcodes eines Skripts gilt. Ich werde die verschiedenen Optimierungsstufen in diesem Artikel jedoch nicht durchgehen, da dies auch ein Artikel für sich wäre.

Stufe 4 - Interpretation

Die letzte Phase ist die Interpretation der Opcodes. Hier werden die Opcodes auf dem Zend Engine (ZE) VM ausgeführt. In dieser Phase gibt es tatsächlich nur sehr wenig zu sagen (zumindest aus hoher Perspektive). Die Ausgabe ist so ziemlich das, was Ihr PHP -Skript über Befehle wie Echo, Print, var_dump usw. ausgibt.

, anstatt zu diesem Zeitpunkt in irgendetwas Komplexes zu graben, ist hier eine lustige Tatsache: PHP benötigt sich selbst als Abhängigkeit, wenn er seine eigene VM generiert. Dies liegt daran

Schlussfolgerung

Wir haben einen kurzen Blick durch die vier Stufen, die der PHP -Interpreter beim Ausführen von PHP -Code durchläuft. Dies hat die Verwendung verschiedener Erweiterungen (einschließlich Tokenizer, PHP-Ast, Opcache und VLD) zur Manipulation und Sichtweise der Ausgabe jeder Stufe beinhaltet.

.

Ich hoffe, dieser Artikel hat Ihnen dazu beigetragen, Ihnen ein besseres ganzheitliches Verständnis des Interpreters von PHP zu vermitteln und die Bedeutung der Opcache -Erweiterung (sowohl für seine Ausgeschnittene als auch für Optimierungsfähigkeiten) zu zeigen.

häufig gestellte Fragen (FAQs) zum PHP -Ausführungsprozess

Welche Rolle spielt der PHP -Interpreter im Ausführungsprozess? Es ist verantwortlich für die Konvertierung des PHP-Quellcodes in maschinelles Lesbarer Code. Der Interpreter liest die PHP -Skriptzeile nach Zeile, interpretiert jede Zeile und führt die erforderlichen Vorgänge aus. Es ist auch verantwortlich für die Behandlung von Fehlern und Ausnahmen während des Ausführungsprozesses. Der PHP -Interpreter ist eine Schlüsselkomponente der PHP -Laufzeitumgebung, die auch den Webserver und die PHP -Erweiterungen umfasst. Der PHP -Ausführungsprozess. Es ist dafür verantwortlich, das PHP -Skript zu analysieren, in Bytecode zu kompilieren und dann die Bytecode auszuführen. Die PHP-Engine verwendet einen zweistufigen Prozess, um PHP-Skripte auszuführen. Zunächst analysiert es das PHP -Skript und konvertiert es in einen abstrakten Syntaxbaum (AST). Dann kompiliert es das AST in Bytecode und führt es aus. Die PHP-Engine enthält außerdem einen Speichermanager und einen Müllsammler, um die Speicherverwendung während des Ausführungsprozesses zu verwalten. -Line Interface (CLI) und Webserverschnittstelle sind zwei verschiedene Möglichkeiten, um PHP -Skripte auszuführen. Die CLI wird zum Ausführen von PHP -Skripten aus der Befehlszeile verwendet, während die Webserverschnittstelle zum Ausführen von PHP -Skripten als Antwort auf Webanforderungen verwendet wird. Der Hauptunterschied zwischen den beiden Schnittstellen ist die Art und Weise, wie sie Eingang und Ausgabe behandeln. In der CLI wird die Eingabe aus der Befehlszeile gelesen und die Ausgabe in die Konsole geschrieben. In der Webserverschnittstelle wird die Eingabe aus der HTTP -Anforderung gelesen, und die Ausgabe wird in die HTTP -Antwort geschrieben. Mechanismus, der es ihm ermöglicht, Fehler während des Ausführungsprozesses zu bewältigen. Wenn ein Fehler auftritt, generiert PHP eine Fehlermeldung und sendet sie an den Fehlerhandler. Der Fehlerhandler kann entweder die Fehlermeldung anzeigen, sie protokollieren oder ignorieren, abhängig von den Fehlerberichterstattungseinstellungen. PHP unterstützt auch die Ausnahmeregelung, sodass es Fehler auf strukturiertere und überschaubare Weise behandelt.

Welche Rolle spielt die PHP -Erweiterungen im Ausführungsprozess? Sie werden während des Ausführungsprozesses in die PHP -Laufzeitumgebung geladen und können verwendet werden, um eine Vielzahl von Aufgaben aus dem Datenbankzugriff bis zur Bildverarbeitung auszuführen. PHP -Erweiterungen werden in C geschrieben und in den Maschinencode zusammengestellt, wodurch sie sehr schnell und effizient sind. Sie sind eine Schlüsselkomponente des PHP -Ökosystems und tragen zu seiner Flexibilität und Leistung bei.

Wie optimiert PHP den Ausführungsprozess? Eine dieser Techniken ist das Opcode -Caching, bei dem die von der PHP -Engine im Speicher erzeugte Bytecode gespeichert werden, damit sie in nachfolgenden Ausführungen wiederverwendet werden kann. Dadurch wird die Notwendigkeit beseitigt, das PHP -Skript jedes Mal zu analysieren und zu kompilieren, wenn es zu erheblichen Leistungsverbesserungen führt. PHP verwendet auch Just-in-Time-Zusammenstellung (Just-in-Time), bei der Bytecode zur Laufzeit in den Maschinencode kompiliert wird, um die Leistung weiter zu verbessern. PHP verfügt über einen integrierten Speichermanager, der während des Ausführungsprozesses die Speicherzuweisung und Deallokation übernimmt. Der Speichermanager weist nach Bedarf den Speicher für Variablen und Datenstrukturen zu und bearbeitet den Speicher, wenn er nicht mehr benötigt wird. PHP hat auch einen Müllsammler, der den Speicher automatisch befreit, der nicht mehr verwendet wird. Dies hilft, Speicherlecks zu verhindern und die Speicherverwendung unter Kontrolle zu halten.

Welche Rolle spielt der Webserver im PHP -Ausführungsprozess? Verfahren. Es ist verantwortlich für die Behandlung von HTTP -Anfragen, das Ausführen von PHP -Skripten als Antwort auf diese Anfragen und das Senden von HTTP -Antworten an den Client. Der Webserver arbeitet eng mit dem PHP -Interpreter und der PHP -Engine zusammen, um PHP -Skripte auszuführen und dynamische Webseiten zu generieren. Die am häufigsten verwendeten Webserver für PHP sind Apache und Nginx. MySQL, Postgresql und SQLite. Es verwendet datenbankspezifische Erweiterungen, um während des Ausführungsprozesses mit diesen Datenbanken zu interagieren. Diese Erweiterungen bieten eine Reihe von Funktionen, mit denen eine Verbindung zur Datenbank hergestellt, SQL -Abfragen ausgeführt, Ergebnisse abgerufen und Fehler verarbeitet werden können. PHP unterstützt auch die Erweiterung der PDO (PHP-Datenobjekte), die eine Datenbank-Agnostic-Schnittstelle für Datenbankinteraktionen bereitstellt.

Wie verarbeitet PHP das Sitzungsmanagement während des Ausführungsprozesses? Wenn eine Sitzung gestartet wird, erstellt PHP eine eindeutige Sitzungs -ID und speichert sie in einem Cookie im Browser des Kunden. Diese Sitzungs -ID wird dann mit jeder nachfolgenden Anforderung an den Server zurückgesandt, sodass PHP den Client identifizieren und die entsprechenden Sitzungsdaten abrufen kann. Die Sitzungsverwaltungsfunktionen von PHP erleichtern die Implementierung der Benutzerauthentifizierung, Einkaufswagen und andere staatliche Funktionen in Webanwendungen.

Das obige ist der detaillierte Inhalt vonWie PHP ausführt - vom Quellcode zum Rendern. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn