Slide 1

Slide 1 text

入門 Hello world

Slide 2

Slide 2 text

自己紹介 ● 西 祐太郎 (長崎県産🐟) ● 何でも屋さん@某クラウドソーシング会社 ○ 専門学校 -> 中堅SI-> Webマーケ系スタートアップ -> オンライン旅行代理店 ● 趣味:距離ガバドライブ🚗 ● PHPカンファレンスは2020から参加 ● GitHub: https://github.com/yuta-ron ● Wantedly: https://www.wantedly.com/id/yutaron

Slide 3

Slide 3 text

● 1-2ヶ月に1回WordPress Meetup (大田区近辺) で遊んでいます ○ エンジニアはあまりいません。 ○ 主に会社のWeb担当とかマーケターとか個人事業主 ○ 趣味でホームページやっている人とか ● 興味のある方はこちらから https://www.meetup.com/ja-JP/tokyo-wordpress-meetup/ 自己紹介(告知)

Slide 4

Slide 4 text

今日話すこと ● 純粋なPHPのお話です。 ● ブラウザがリクエストを投げて、帰ってくるまでのお話です。 話さないこと ● Laravel/CakePHPなどのフレームワークの話

Slide 5

Slide 5 text

前提条件 ● nginx1.23.1 (Source) + PHP 8.1.10 (Docker)

Slide 6

Slide 6 text

期待する動作

Slide 7

Slide 7 text

準備するもの ● 適切なマシン (今回はMacBookAir M1 (Monterey)を使用。なんでもOKです) ● ソースコード ○ php/php-src (コード追いかける用) ○ nginx/nginx (デバッグビルドして適当にログ入れるとイメージ湧きます) ● WireShark (パケットさえ見れればなんでもOKです)

Slide 8

Slide 8 text

PHPがどう動くか ❯ php -a Interactive shell php > echo 'Hello world'; Hello world php >

Slide 9

Slide 9 text

PHPが実行されるまで ● PHPはコードがそのまま実行されるわけではありません。 ○ インタプリタ言語(リクエストの度に処理実行) ● コンパイルする(バイトコード生成) ○ 字句解析 ->(トークン化)-> 構文解析 ■ 抽象構文木 (AST) ● 毎回コンパイルするんじゃ効率悪いよ🥺 ○ これをキャッシュ(OPCache PHP5.5~) ■ バイトコードをZend VM上で実行

Slide 10

Slide 10 text

PHPが実行されるまで ● PHPはコードがそのまま実行されるわけではありません。 ○ インタプリタ言語(リクエストの度に処理実行) ● コンパイルする(バイトコード生成) ○ 字句解析 ->(トークン化)-> 構文解析 ■ 抽象構文木 (AST) ● 毎回コンパイルするんじゃ効率悪いよ🥺 ○ これをキャッシュ(OPCache PHP5.5~) ■ バイトコードをZend VM上で実行

Slide 11

Slide 11 text

ここまでの心境 ● 気になりまくり ○ バイトコードって何やねん(もやもや☁)

Slide 12

Slide 12 text

ここまでの心境 ● バイトコードって何やねん(もやもや☁) ○ お、簡単に見れるらしいぞ。 https://www.php.net/manual/ja/opcache.configuration.php

Slide 13

Slide 13 text

PHPが実行されるまで ● PHPはコードがそのまま実行されるわけではありません。 ○ インタプリタ言語(リクエストの度に処理実行) ● コンパイルする(バイトコード生成) ○ 字句解析 ->(トークン化)-> 構文解析 ■ 抽象構文木 (AST) ● 毎回コンパイルするんじゃ効率悪いよ🥺 ○ これをキャッシュ(OPCache PHP5.5~) ■ バイトコードをZend VM上で実行

Slide 14

Slide 14 text

PHPがどう分解されていくか(字句解析編) ● 今回はこのような簡単なコードで検証

Slide 15

Slide 15 text

PHPがどう分解されていくか(字句解析編) ● PHPの標準関数で簡単に見える https://www.php.net/manual/ja/function.token-get-all.php

Slide 16

Slide 16 text

● 1列目 → トークン値 ● 2列目 → トークン ● 3列目 → 行番号 PHPがどう分解されていくか(字句解析編) ● さっきのソースを分解するとこんな感じ

Slide 17

Slide 17 text

PHPがどう分解されていくか(構文解析編) ● さっきのトークンから、このような ASTを作って構文の妥当性を検証。 ○ 四則演算、関数、クラス諸々が入るともはや解読不能 https://github.com/ircmaxell/php-ast-visualizer

Slide 18

Slide 18 text

PHPがどう分解されていくか (バイトコード編) ● 今までのステップを経てバイトコードが生成される。 ○ Zend VMはこれを実行する。 ←実際の命令 php.iniでopcacheの有効化が必要 FYI: ダンプには https://github.com/derickr/vld を使うのもおすすめ

Slide 19

Slide 19 text

php-srcを 読んでみる static void zend_compile_echo(zend_ast *ast)

Slide 20

Slide 20 text

トークン値 シンボル名(token_name関数で取得) トークン値がソース内部でどう解釈されるか ● さっきのソースを分解するとこんな感じ 267 -> T_INLINE_HTML 389 -> T_OPEN_TAG 392 -> T_WHITESPACE 291 -> T_ECHO 291 -> T_WHITESPACE 291 -> T_CONSTANT_ENCAPSED_STRING

Slide 21

Slide 21 text

トークン値がソース内部でどう解釈されるか ● さっきのソースを分解するとこんな感じ 267 -> T_INLINE_HTML 389 -> T_OPEN_TAG 392 -> T_WHITESPACE 291 -> T_ECHO 291 -> T_WHITESPACE 291 -> T_CONSTANT_ENCAPSED_STRING トークン値 シンボル名(token_name関数で取得)

Slide 22

Slide 22 text

php-srcを読んでみる T_ECHOでgrepかけてみる

Slide 23

Slide 23 text

php-srcを読んでみる T_ECHOでgrepかけてみる echoという文字を見つけたら T_ECHOでトークン化

Slide 24

Slide 24 text

php-srcを読んでみる T_ECHOでgrepかけてみる ASTを生成

Slide 25

Slide 25 text

php-srcを読んでみる T_ECHOでgrepかけてみる バイトコードを生成

Slide 26

Slide 26 text

php-srcを読んでみる ● 今までのステップを経てバイトコードが生成される。 ○ バイトコードから先の世界は省略します。 ←実際の命令

Slide 27

Slide 27 text

nginx編 location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; }

Slide 28

Slide 28 text

流れ ブラウザからのリクエストをnginxが橋渡しする

Slide 29

Slide 29 text

流れ ブラウザからのリクエストをnginxが橋渡ししてfpmサーバへ

Slide 30

Slide 30 text

流れ nginx -> php-fpmの流れ curl http://localhost:10081(/) nginx nginx.conf (default.conf) 設定ファイルで PHPファイルのパスを解決 fpmサーバの接続先を設定 (unixソケット指定の場合もあり) localhost:9000 (fpmサーバ)へ 対象のPHPのファイル実行に 必要な情報を伝達

Slide 31

Slide 31 text

流れ nginx -> php-fpmに飛んでいるリクエスト(補足)

Slide 32

Slide 32 text

流れ ● DOCUMENT_ROOT (nginx.confのroot) はphpのコードが動作する環 境に合わせる。 ● webサーバとappサーバが独立している場合は要注意。 (コンテナ環境(docker compose/ECS) など) リクエスト nginx.conf

Slide 33

Slide 33 text

今までの流れをざっくり

Slide 34

Slide 34 text

まとめ ● サンプルコードを用いたPHPのコード実行の流れ ○ PHPのトークン化 -> AST -> バイトコード生成までの流れ ● ブラウザからPHPのコードを実行するまでの流れ ○ webサーバとfpmサーバ間でやりとりする ○ 上記がどのように繋がって疎通しているか ■ 該当ソースコードの図示

Slide 35

Slide 35 text

参考 ● PHP の echo と print の違い (闇) https://y-uti.hatenablog.jp/entry/2015/12/07/000027 ● ミドルウェアのソースコードリーディングのすすめ https://developers.freee.co.jp/entry/how-to-read-source-code-of-middleware ● Zend Engine 2 オペコード http://php.adamharvey.name/manual/ja/internals2.opcodes.php ● PHP7 と HHVM/Hack 言語って何が違うの? https://www.infiniteloop.co.jp/tech-blog/2018/07/difference-between-php7-and-hhvm-hack/ ● VLDでPHPのオペコードを確認する https://saitodev.co/article/VLD%E3%81%A7PHP%E3%81%AE%E3%82%AA%E3%83%9A%E3%82%B3%E3%83%B C%E3%83%89%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B ● 詳説ぺちぺち https://www.slideshare.net/do_aki/ss-11304937 ● PHP AST 徹底解説 https://www.slideshare.net/do_aki/php-ast ● JIT のコードを読んでみた https://www.slideshare.net/y-uti/jit-70023246 ● 第9章 速習yacc https://i.loveruby.net/ja/rhg/book/yacc.html ありがとうございました!

Slide 36

Slide 36 text

おわり