ホームページ > バックエンド開発 > PHPチュートリアル > PHPの実行方法 - ソースコードからレンダリングまで

PHPの実行方法 - ソースコードからレンダリングまで

Jennifer Aniston
リリース: 2025-02-10 10:11:11
オリジナル
808 人が閲覧しました

PHPの実行方法 - ソースコードからレンダリングまで

この記事は、Younes Rafieによってピアレビューされました。 SetePointコンテンツを最高にするためにSitePointのピアレビュアーのすべてに感謝します! Rubyコードの実行方法に関する最近の記事に触発されたこの記事では、PHPコードの実行プロセスについて説明しています。


キーテイクアウト

PHPの実行方法 - ソースコードからレンダリングまで

PHPコードの実行には、レクシング、解析、コンピレーション、および解釈の4つの段階が含まれます。 PHPソースコードを機械可読コードに変換するプロセスでは、各段階が重要です。

レックス、またはトークン化は、文字列(PHPソースコード)を一連のトークンに変換するプロセスです。各トークンは、一致した値の名前付き識別子です。この段階には、一致したトークンの語彙素とライン番号も保存されます。

解析段階は、トークン順序の有効性を検証し、抽象的な構文ツリー(AST)を生成します。 ASTは、コンピレーション段階で使用されるソースコードのツリービューです。
    コンピレーション段階は、ASTを横断することによりオペコードを放出し、文字通りの引数で関数呼び出しを解決し、定数数学的式を折りたたむような最適化を実行します。この段階の出力は、opcache、vld、およびphpdbgを使用して検査できます。
  • 解釈段階は、Zend Engine(ZE)VMでオペコードが実行される最終段階です。この段階の出力は、PHPスクリプトがエコー、印刷、var_dumpなどのコマンドを介して出力するものです。
  • はじめに
  • PHPコードを実行すると、ボンネットの下で多くのことが起こっています。大まかに言えば、PHPインタープリターはコードを実行するときに4つの段階を通過します。
  • lexing
  • 解析
コンピレーション

解釈

    この記事では、これらの段階をスキムし、各段階から出力を表示して何が起こっているかを実際に確認する方法を示します。使用される拡張機能の一部はすでにPHPのインストールの一部である必要がありますが(トークンザーやOpcacheなど)、他のものは手動でインストールして有効にする必要があること(PHP-ASTやVLDなど)。
  1. ステージ1 - lexing
  2. lexing(またはトークン化)は、文字列(この場合はPHPソースコード)を一連のトークンに変換するプロセスです。トークンは、一致した値の単に指名された識別子です。 PHPはRE2Cを使用して、Zend_language_scanner.l定義ファイルからlexerを生成します。
  3. トークン剤拡張を介してレクシング段階の出力を見ることができます:
  4. outputs:
  5. $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>
    ログイン後にコピー
    ログイン後にコピー

    上記の出力から注目に値するポイントがいくつかあります。最初のポイントは、ソースコードのすべてのピースがトークンという名前ではないということです。代わりに、一部のシンボルは、それ自体のトークンと見なされます(=、;、:、?など)。 2番目のポイントは、Lexerが実際にトークンのストリームを単に出力するだけではないということです。また、ほとんどの場合、語彙素(トークンと一致する値)と一致したトークンのライン番号(スタックトレースのようなものに使用されます)を保存します。

    ステージ2 - 解析

    パーサーも生成され、今回はBNF文法ファイルを介してバイソンを使用します。 PHPは、LALR(1)(先に見て、左から右へ)の文脈のない文法を使用します。先を見先の部分は、パーサーがnトークンを先に見ることができることを意味します(この場合、1、この場合)、解析中に遭遇する可能性のある曖昧さを解決することができます。左から右への部分は、トークンストリームを左から右へと解析することを意味します。

    生成されたパーサーステージには、入力としてlexerからトークンストリームを取り、2つのジョブがあります。まず、BNF文法ファイルで定義されている文法規則のいずれかと一致させようとすることにより、トークン順序の有効性を検証します。これにより、有効な言語構造がトークンストリームのトークンによって形成されることが保証されます。パーサーの2番目のジョブは、

    抽象的構文ツリー(AST)を生成することです。次の段階で使用されるソースコードのツリービュー(コンパイル)。 PHP-AST拡張機能を使用してパーサーによって生成されるASTの形式を

    初歩的なコードのASTを見てみましょう:

    output:

    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) ";"
    
    ログイン後にコピー
    ログイン後にコピー
    ツリーノード(通常はタイプASTNODEのタイプです)にはいくつかのプロパティがあります。

    種類 - ノードタイプを描写する整数値。それぞれに対応する定数があります(例:AST_STMT_LIST => 132、AST_ASSIGN => 517、AST_VAR => 256)
    $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>
    ログイン後にコピー
    ログイン後にコピー

    フラグ - 過負荷の動作を指定する整数(たとえば、ASTAST_BINARY_OPノードには、どのバイナリ操作が発生しているかを区別するフラグがあります)

    リネノ - トークン情報から以前に見られるように、ライン番号
  • 子供 - サブノード、通常、ノードの一部がさらに分解されます(たとえば、関数ノードには子供があります:パラメーター、リターンタイプ、ボディなど)
  • この段階のAST出力は、静的コードアナライザー(PHANなど)などのツールのために作業するのに便利です。

    ステージ3 - コンピレーション

    コンピレーション段階はASTを消費し、ツリーを再帰的に横断することによりオペコードを放出します。この段階では、いくつかの最適化も実行されます。これらには、文字通りの引数(strlen( "abc")からint(3)などのいくつかの関数呼び出しを解決し、折り畳み一定の数学式(60 * 60 * 24からint(86400)など)。

    OpCache、VLD、PHPDBGなど、さまざまな方法で、この段階でOPCODE出力を検査できます。出力がより友好的であると感じているので、これにVLDを使用します。

    次のfile.phpスクリプトの出力を見てみましょう。

    次のコマンドを実行します:
$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>
ログイン後にコピー
ログイン後にコピー

出力は
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) ";"
ログイン後にコピー
ログイン後にコピー
です

オプコードは、基本操作に従うのに十分な元のソースコードに似ています。 (この記事のオペコードの詳細については掘り下げるつもりはありません。それ自体がいくつかの記事全体を撮るからです。)上記のスクリプトのオペコードレベルで最適化は適用されませんでしたが、見ることができるように、コンパイルフェーズは定数条件(php_version === '7.1.0-dev')をtrueに解決することでいくつかを作成しました。
$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>
ログイン後にコピー
ログイン後にコピー
opcacheは、単にオペコードをキャッシュするだけではありません(したがって、レクシング、解析、コンピレーション段階をバイパスします)。また、さまざまなレベルの最適化も詰め込まれています。最適化レベルを4つのパスに上げて、出てくるものを確認しましょう。

コマンド:

output:

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
            )
        )
    )
)
ログイン後にコピー
一定の条件が削除されており、2つのエコー命令が単一の命令に圧縮されていることがわかります。これらは、スクリプトのオペコード上でパスを実行するときにOpcacheが適用する多くの最適化の味です。ただし、この記事ではさまざまな最適化レベルを通過することはありません。それ自体が記事でもあるからです。

ステージ4 - 解釈

<span>if (PHP_VERSION === '7.1.0-dev') {
</span>    <span>echo 'Yay', PHP_EOL;
</span><span>}
</span>
ログイン後にコピー
最終段階は、オプコードの解釈です。これは、Zend Engine(ZE)VMでオペコードが実行される場所です。実際、この段階についてはほとんど言うことはほとんどありません(少なくとも高レベルの観点から)。出力は、echo、print、var_dumpなどのコマンドを介して、PHPスクリプトが出力されるものであろうと、

この段階で複雑なものを掘り下げる代わりに、ここに面白い事実があります。PHPは、独自のVMを生成する際に依存関係として必要です。これは、VMがPHPスクリプトによって生成されたためです。

結論

PHPコードを実行するときにPHPインタープリターが通過する4つの段階を簡単に確認しました。これには、各ステージの出力を操作して表示するために、さまざまな拡張機能(トークン剤、PHP-AST、Opcache、およびVLDを含む)を使用しています。

この記事が、PHPの通訳のより良い全体的な理解を提供するのに役立つことを願っています。また、Opcache拡張の重要性(キャッシュ能力と最適化能力の両方)を示しました。 PHP実行プロセスに関するよくある質問(FAQ)

実行プロセスにおけるPHP通訳者の役割は何ですか?

PHPインタープリターは、PHP実行プロセスで重要な役割を果たします。 PHPソースコードを機械可読コードに変換する責任があります。通訳者は、PHPスクリプトラインを線で読み取り、各行を解釈し、必要な操作を実行します。また、実行プロセス中にエラーと例外を処理する責任があります。 PHPインタープリターはPHPランタイム環境の重要なコンポーネントであり、WebサーバーとPHP拡張機能も含まれます。

PHPエンジンはどのように機能しますか? PHP実行プロセス。 PHPスクリプトを解析し、それをBytecodeにコンパイルし、ByteCodeを実行する責任があります。 PHPエンジンは、2段階のプロセスを使用してPHPスクリプトを実行します。まず、PHPスクリプトを解析し、それを抽象的構文ツリー(AST)に変換します。次に、ASTをBytecodeにコンパイルして実行します。 PHPエンジンには、実行プロセス中にメモリマネージャーとゴミコレクターも含まれています。 -lineインターフェイス(CLI)とWebサーバーインターフェイスは、PHPスクリプトを実行する2つの異なる方法です。 CLIはコマンドラインからPHPスクリプトの実行に使用され、WebサーバーインターフェイスはWeb要求に応じてPHPスクリプトを実行するために使用されます。 2つのインターフェイスの主な違いは、入力と出力を処理する方法です。 CLIでは、入力がコマンドラインから読み取り、出力がコンソールに書き込まれます。 Webサーバーインターフェイスでは、入力がHTTP要求から読み取り、出力はHTTP応答に書き込まれます。実行プロセス中にエラーを処理できるメカニズム。エラーが発生すると、PHPはエラーメッセージを生成し、エラーハンドラーに送信します。エラーハンドラーは、エラーの報告設定に応じて、エラーメッセージを表示したり、ログにしたり、無視したりできます。 PHPは例外処理もサポートしているため、より構造化された管理可能な方法でエラーを処理できます。

実行プロセスにおけるPHP拡張の役割は何ですか?

PHP拡張は、PHP言語に新しい機能と機能を追加するモジュールです。実行プロセス中にPHPランタイム環境にロードされ、データベースアクセスから画像処理まで、幅広いタスクを実行するために使用できます。 PHP拡張機能はCで記述され、マシンコードにコンパイルされるため、非常に高速で効率的になります。それらはPHPエコシステムの重要なコンポーネントであり、その柔軟性とパワーに貢献しています。これらの手法の1つは、PHPエンジンによって生成されたバイトコードをメモリに保存して、後続の実行で再利用できるようにすることを含むオペコードキャッシングです。これにより、PHPスクリプトが実行されるたびに解析してコンパイルする必要性がなくなり、パフォーマンスが大幅に向上します。 PHPはまた、ジャストインタイム(JIT)コンピレーションを使用します。これには、実行時にバイトコードをマシンコードにコンパイルしてパフォーマンスをさらに向上させます。 PHPには、実行プロセス中にメモリの割り当てと取引を処理するメモリマネージャーが組み込まれています。メモリマネージャーは、必要に応じて変数とデータ構造のメモリを割り当て、不要になったときにメモリを扱います。 PHPには、使用されなくなったメモリを自動的に解放するゴミコレクターもあります。これにより、メモリの漏れを防ぎ、メモリの使用量を制御し続けるのに役立ちます。プロセス。 HTTPリクエストの処理、これらの要求に応じてPHPスクリプトの実行、およびHTTP応答をクライアントに送信する責任があります。 Webサーバーは、PHPインタープリターとPHPエンジンと緊密に連携して、PHPスクリプトを実行して動的なWebページを生成します。 PHPで最も一般的に使用されるWebサーバーは、Apacheとnginxです。 mysql、postgresql、およびsqlite。データベース固有の拡張機能を使用して、実行プロセス中にこれらのデータベースと対話します。これらの拡張機能は、データベースに接続し、SQLクエリを実行し、結果を取得し、エラーを処理するために使用できる一連の機能を提供します。 PHPは、PDO(PHPデータオブジェクト)拡張機能もサポートしています。これは、データベースインタラクションのデータベース存在インターフェイスを提供します。

実行プロセス中のPHPはセッション管理をどのように処理しますか?

PHPにはセッション管理のサポートが組み込まれているため、異なるHTTP要求間で状態を維持できます。セッションが開始されると、PHPは一意のセッションIDを作成し、クライアントのブラウザのCookieに保存します。このセッションIDは、その後のリクエストごとにサーバーに送信され、PHPがクライアントを識別し、対応するセッションデータを取得できるようにします。 PHPのセッション管理機能により、ユーザー認証、ショッピングカート、その他のステートフルな機能をWebアプリケーションに簡単に実装できます。

以上がPHPの実行方法 - ソースコードからレンダリングまでの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート