Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Let's Take a Peek at PHP Parser 5.x!
Search
inouehi
March 16, 2025
Programming
0
260
Let's Take a Peek at PHP Parser 5.x!
『5系になったPHP Parserをのぞいてみよう!』
PHPerKaigi 2025
2025-03-23 15:20〜 Track A
https://phperkaigi.jp/2025/
inouehi
March 16, 2025
Tweet
Share
More Decks by inouehi
See All by inouehi
2025 Reflections on Working with Natural Language
inouehi
0
92
Exploring Engineering in Workflow Development
inouehi
0
57
Using AI Tools Around Software Development
inouehi
0
1.5k
Learning Kotlin with detekt
inouehi
1
770
Learning numeric-like string based on RFC
inouehi
0
120
What We Can Learn From OSS
inouehi
0
1.1k
Learning PHP and Static Analysis with PHP Parser
inouehi
2
800
Understanding Ast By Looking
inouehi
0
2.3k
Improve Our Development Habits by Measuring Productivity and Maintainability
inouehi
1
1.6k
Other Decks in Programming
See All in Programming
組み合わせ爆発にのまれない - 責務分割 x テスト
halhorn
1
160
Python札幌 LT資料
t3tra
6
1k
大規模Cloud Native環境におけるFalcoの運用
owlinux1000
0
190
俺流レスポンシブコーディング 2025
tak_dcxi
14
9.5k
Go コードベースの構成と AI コンテキスト定義
andpad
0
140
JETLS.jl ─ A New Language Server for Julia
abap34
2
450
AI 駆動開発ライフサイクル(AI-DLC):ソフトウェアエンジニアリングの再構築 / AI-DLC Introduction
kanamasa
11
3.8k
Context is King? 〜Verifiability時代とコンテキスト設計 / Beyond "Context is King"
rkaga
10
1.4k
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
310
脳の「省エネモード」をデバッグする ~System 1(直感)と System 2(論理)の切り替え~
panda728
PRO
0
120
認証・認可の基本を学ぼう後編
kouyuume
0
250
Full-Cycle Reactivity in Angular: SignalStore mit Signal Forms und Resources
manfredsteyer
PRO
0
170
Featured
See All Featured
WENDY [Excerpt]
tessaabrams
8
35k
GraphQLとの向き合い方2022年版
quramy
50
14k
Paper Plane
katiecoart
PRO
0
44k
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
57
37k
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
0
63
The #1 spot is gone: here's how to win anyway
tamaranovitovic
1
860
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
190
Java REST API Framework Comparison - PWX 2021
mraible
34
9k
Utilizing Notion as your number one productivity tool
mfonobong
2
190
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
110
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
132
19k
Transcript
5系になったPHP Parser をのぞいてみよう! 2025/03/23 PHPerKaigi 2025 LT
About Me • Hiroki Inoue • Software Engineer • Engineering
Manager @ Smartround Inc. 2
トーク概要 このトークでは、PHP Parserで定義されているノードの全体像を整理します。 コードと、ノードないしASTの対応関係を見つめ、理解に迫ります。 年に1度、5分だけ、1年分の感謝を込めてPHP Parserだけを見つめASTに想いを馳せる。そんな時間に したいと思います。 3 https://fortee.jp/phperkaigi-2025/proposal/a792f343-21f2-47fb-9e45-243a77dd57af
誰向けのトーク? 4
誰向けのトーク? • 静的解析ツールを理解するヒントを得たい方 5
誰向けのトーク? • 静的解析ツールを理解するヒントを得たい方 • PHPStanやRector等のカスタムルールを作成したい方 6
誰向けのトーク? • 静的解析ツールを理解するヒントを得たい方 • PHPStanやRector等のカスタムルールを作成したい方 • 静的解析の恩恵を受けている方 7
誰向けのトーク? • 静的解析ツールを理解するヒントを得たい方 • PHPStanやRector等のカスタムルールを作成したい方 • 静的解析の恩恵を受けている方 8
誰向けのトーク? • 静的解析ツールを理解するヒントを得たい方 • PHPStanやRector等のカスタムルールを作成したい方 • 静的解析の恩恵を受けている方 9
つまり あなた 10
伝えたいこと 11
伝えたいこと • PHP Parserの働きを理解するためのヒント 12
伝えたいこと • PHP Parserの働きを理解するためのヒント • ノードの全体像 13
伝えたいこと • PHP Parserの働きを理解するためのヒント • ノードの全体像 • ノードとコードの対応関係 14
それと 15
尊敬 16
感謝 17
愛 18
ありがとうPHP Parser My utmost appreciation and heartfelt thanks for PHP
Parser 19
ありがとうnikic-san and nikic-san 20
俺たちは PHP Parser から 恩恵を受けまくっている 21
PHPStan 22 https://phpstan.org/blog/find-bugs-in-your-code-without-writing-tests#on-the-shoulders-of-giants
Rector 23 https://getrector.com/documentation/how-rector-works#content-21-prepare-phase
Psalm 24 https://psalm.dev/docs/contributing/philosophy/
php-class-diagram 25 https://github.com/smeghead/php-class-diagram
ノードをのぞいてみよう 26
前提 PHP Parser v5.3.1 に基づいて発表資料を作成します。 27
ノードとは “The parser produces an Abstract Syntax Tree (AST) also
known as a node tree.” 28 https://github.com/nikic/PHP-Parser/blob/master/doc/0_Introduction.markdown#what-output-does-it-produce
ノードとは “The parser produces an Abstract Syntax Tree (AST) also
known as a node tree.” 29 array( 0: Stmt_Echo( exprs: array( 0: Scalar_String( value: The ) 1: Scalar_String( value: World ) ) ) ) <?php echo 'The', 'World';
ノードとは “The parser produces an Abstract Syntax Tree (AST) also
known as a node tree.” 30 array( 0: Stmt_Echo( exprs: array( 0: Scalar_String( value: The ) 1: Scalar_String( value: World ) ) ) )
ノードとは “The parser produces an Abstract Syntax Tree (AST) also
known as a node tree.” 31 array( 0: Stmt_Echo( exprs: array( 0: Scalar_String( value: The ) 1: Scalar_String( value: World ) ) ) ) ノード
参考 • 『木を見て!森を見て!目で見てわかるAST(抽象構文木)』[1] • 『PHP Parserで学ぶPHP』[2] 32 1. https://speakerdeck.com/inouehi/understanding-ast-by-looking 2.
https://speakerdeck.com/inouehi/php-parserdexue-buphp
ノードの全体像 nikic/php-parser/lib/PhpParser/Node/ 配下に190個のファイルがある。 33 ./Node ├── Expr │ ├── AssignOp
│ │ ├── BitwiseAnd.php │ │ ├── BitwiseOr.php │ │ ├── BitwiseXor.php │ │ ├── Coalesce.php │ │ ├── Concat.php │ │ ├── Div.php │ │ ├── Minus.php │ │ ├── Mod.php │ │ ├── Mul.php │ │ ├── Plus.php │ │ ├── Pow.php │ │ ├── ShiftLeft.php
ノードの全体像 34 │ │ └── ShiftRight.php │ ├── BinaryOp │
│ ├── BitwiseAnd.php │ │ ├── BitwiseOr.php │ │ ├── BitwiseXor.php │ │ ├── BooleanAnd.php │ │ ├── BooleanOr.php │ │ ├── Coalesce.php │ │ ├── Concat.php │ │ ├── Div.php │ │ ├── Equal.php │ │ ├── Greater.php │ │ ├── GreaterOrEqual.php │ │ ├── Identical.php │ │ ├── LogicalAnd.php │ │ ├── LogicalOr.php │ │ ├── LogicalXor.php │ │ ├── Minus.php │ │ ├── Mod.php │ │ ├── Mul.php │ │ ├── NotEqual.php │ │ ├── NotIdentical.php │ │ ├── Plus.php
ノードの全体像 35 │ │ ├── Pow.php │ │ ├── ShiftLeft.php
│ │ ├── ShiftRight.php │ │ ├── Smaller.php │ │ ├── SmallerOrEqual.php │ │ └── Spaceship.php │ ├── Cast │ │ ├── Array_.php │ │ ├── Bool_.php │ │ ├── Double.php │ │ ├── Int_.php │ │ ├── Object_.php │ │ ├── String_.php │ │ └── Unset_.php │ ├── ArrayDimFetch.php │ ├── ArrayItem.php │ ├── Array_.php │ ├── ArrowFunction.php │ ├── Assign.php │ ├── AssignOp.php │ ├── AssignRef.php │ ├── BinaryOp.php │ ├── BitwiseNot.php
ノードの全体像 36 │ ├── BooleanNot.php │ ├── CallLike.php │ ├──
Cast.php │ ├── ClassConstFetch.php │ ├── Clone_.php │ ├── Closure.php │ ├── ClosureUse.php │ ├── ConstFetch.php │ ├── Empty_.php │ ├── Error.php │ ├── ErrorSuppress.php │ ├── Eval_.php │ ├── Exit_.php │ ├── FuncCall.php │ ├── Include_.php │ ├── Instanceof_.php │ ├── Isset_.php │ ├── List_.php │ ├── Match_.php │ ├── MethodCall.php │ ├── New_.php │ ├── NullsafeMethodCall.php │ ├── NullsafePropertyFetch.php
ノードの全体像 nikic/php-parser/lib/PhpParser/Node/ 配下に190個のファイルがある。 • 抽象 … 12個 37
ノードの全体像 nikic/php-parser/lib/PhpParser/Node/ 配下に190個のファイルがある。 • 抽象 … 12個 • エイリアス …
10個 38
ノードの全体像 nikic/php-parser/lib/PhpParser/Node/ 配下に190個のファイルがある。 • 抽象 … 12個 • エイリアス …
10個 • 具象 … 168個 39
抽象 1. PhpParser\Node\Expr\AssignOp 2. PhpParser\Node\Expr\BinaryOp 3. PhpParser\Node\Expr\Calllike 4. PhpParser\Node\Expr\Cast 5.
PhpParser\Node\Scalar\MagicConst 6. PhpParser\Node\Stmt\ClassLike 7. PhpParser\Node\Stmt\TraitUseAdaptation 8. PhpParser\Node\ComplexType 9. PhpParser\Node\Expr 10. PhpParser\Node\Functionlike 11. PhpParser\Node\Scalar 12. PhpParser\Node\Stmt 40
エイリアス 1. PhpParser\Node\Expr\ArrayItem 2. PhpParser\Node\Expr\ClosureUse 3. PhpParser\Node\Scalar\DNumber 4. PhpParser\Node\Scalar\Encapsed 5.
PhpParser\Node\Scalar\EncapsedStringPart 6. PhpParser\Node\Scalar\LNumber 7. PhpParser\Node\Stmt\DeclareDeclare 8. PhpParser\Node\Stmt\PropertyProperty 9. PhpParser\Node\Stmt\StaticVar 10. PhpParser\Node\Stmt\UseUse 41
コードとノードの対応表 # | コード | ノード | ------------------------------------------------------------------------------------------- 1 |
$a &= $b; | Node\Expr\AssignOp\BitwiseAnd | 2 | $a |= $b; | Node\Expr\AssignOp\BitwiseOr | 3 | $a ^= $b; | Node\Expr\AssignOp\BitwiseXor | 4 | $a ??= $b; | Node\Expr\AssignOp\Coalesce | 5 | $a .= $b; | Node\Expr\AssignOp\Concat | 6 | $a /= $b; | Node\Expr\AssignOp\Div | 7 | $a -= $b; | Node\Expr\AssignOp\Minus | 8 | $a %= $b; | Node\Expr\AssignOp\Mod | 9 | $a *= $b; | Node\Expr\AssignOp\Mul | 10 | $a += $b; | Node\Expr\AssignOp\Plus | 11 | $a **= $b; | Node\Expr\AssignOp\Pow | 42
BitwiseAnd をのぞいてみる 1 | $a &= $b; | Node\Expr\AssignOp\BitwiseAnd |
43
コードとノードの対応表 12 | $a <<= $b; | Node\Expr\AssignOp\ShiftLeft | 13
| $a >>= $b; | Node\Expr\AssignOp\ShiftRight | 14 | $a & $b; | Node\Expr\BinaryOp\BitwiseAnd | 15 | $a | $b; | Node\Expr\BinaryOp\BitwiseOr | 16 | $a ^ $b; | Node\Expr\BinaryOp\BitwiseXor | 17 | $a && $b; | Node\Expr\BinaryOp\BooleanAnd | 18 | $a || $b; | Node\Expr\BinaryOp\BooleanOr | 19 | $a ?? $b; | Node\Expr\BinaryOp\Coalesce | 20 | $a . $b; | Node\Expr\BinaryOp\Concat | 21 | $a / $b; | Node\Expr\BinaryOp\Div | 22 | $a == $b; | Node\Expr\BinaryOp\Equal | 23 | $a > $b; | Node\Expr\BinaryOp\Greater | 24 | $a >= $b; | Node\Expr\BinaryOp\GreaterOrEqual | 44
コードとノードの対応表 25 | $a === $b; | Node\Expr\BinaryOp\Identical | 26
| $a and $b; | Node\Expr\BinaryOp\LogicalAnd | 27 | $a or $b; | Node\Expr\BinaryOp\LogicalOr | 28 | $a xor $b; | Node\Expr\BinaryOp\LogicalXor | 29 | $a - $b; | Node\Expr\BinaryOp\Minus | 30 | $a % $b; | Node\Expr\BinaryOp\Mod | 31 | $a * $b; | Node\Expr\BinaryOp\Mul | 32 | $a != $b; | Node\Expr\BinaryOp\NotEqual | 33 | $a !== $b; | Node\Expr\BinaryOp\NotIdentical | 34 | $a + $b; | Node\Expr\BinaryOp\Plus | 35 | $a ** $b; | Node\Expr\BinaryOp\Pow | 36 | $a << $b; | Node\Expr\BinaryOp\ShiftLeft | 37 | $a >> $b; | Node\Expr\BinaryOp\ShiftRight | 45
コードとノードの対応表 38 | $a < $b; | Node\Expr\BinaryOp\Smaller | 39
| $a <= $b; | Node\Expr\BinaryOp\SmallerOrEqual | 40 | $a <=> $b; | Node\Expr\BinaryOp\Spaceship | 41 | (array)$a; | Node\Expr\Cast\Array_ | 42 | (bool)$a; | Node\Expr\Cast\Bool_ | 43 | (float)$a; | Node\Expr\Cast\Double | 44 | (int)$a; | Node\Expr\Cast\Int_ | 45 | (object)$a; | Node\Expr\Cast\Object_ | 46 | (string)$a; | Node\Expr\Cast\String_ | 47 | (unset)$a; | Node\Expr\Cast\Unset_ | 48 | $a["b"]; | Node\Expr\ArrayDimFetch | 49 | [1, 2, 3]; | Node\Expr\Array_ | 50 | fn($a) => $a; | Node\Expr\ArrowFunction | 46
コードとノードの対応表 51 | $a = $b; | Node\Expr\Assign | 52
| $a =& $b; | Node\Expr\AssignRef | 53 | ~$a; | Node\Expr\BitwiseNot | 54 | !$a; | Node\Expr\BooleanNot | 55 | A::B; | Node\Expr\ClassConstFetch | 56 | clone $a; | Node\Expr\Clone_ | 57 | function() {}; | Node\Expr\Closure | 58 | null; | Node\Expr\ConstFetch | 59 | empty($a); | Node\Expr\Empty_ | 60 | $a->; | Node\Expr\Error | 61 | @$a; | Node\Expr\ErrorSuppress | 62 | eval($a); | Node\Expr\Eval_ | 63 | exit; | Node\Expr\Exit_ | 47
コードとノードの対応表 64 | a(); | Node\Expr\FuncCall | 65 | include
"a.php"; | Node\Expr\Include_ | 66 | $a instanceof A; | Node\Expr\Instanceof_ | 67 | isset($a); | Node\Expr\Isset_ | 68 | list($a, $b) = $array; | Node\Expr\List_ | 69 | match($a) { 1 => 2 }; | Node\Expr\Match_ | 70 | $a->b(); | Node\Expr\MethodCall | 71 | new A(); | Node\Expr\New_ | 72 | $a?->b(); | Node\Expr\NullsafeMethodCall | 73 | $a?->b; | Node\Expr\NullsafePropertyFetch | 74 | $a--; | Node\Expr\PostDec | 75 | $a++; | Node\Expr\PostInc | 76 | --$a; | Node\Expr\PreDec | 48
コードとノードの対応表 77 | ++$a; | Node\Expr\PreInc | 78 | print($a);
| Node\Expr\Print_ | 79 | $a->b; | Node\Expr\PropertyFetch | 80 | `a`; | Node\Expr\ShellExec | 81 | A::b(); | Node\Expr\StaticCall | 82 | A::$b; | Node\Expr\StaticPropertyFetch | 83 | $a ? $b : $c; | Node\Expr\Ternary | 84 | throw new Exception(); | Node\Expr\Throw_ | 85 | -$a; | Node\Expr\UnaryMinus | 86 | +$a; | Node\Expr\UnaryPlus | 87 | $a; | Node\Expr\Variable | 88 | yield from $a; | Node\Expr\YieldFrom | 89 | yield $a; | Node\Expr\Yield_ | 49
コードとノードの対応表 90 | \A; | Node\Name\FullyQualified | 91 | namespace\A;
| Node\Name\Relative | 92 | __CLASS__; | Node\Scalar\MagicConst\Class_ | 93 | __DIR__; | Node\Scalar\MagicConst\Dir | 94 | __FILE__; | Node\Scalar\MagicConst\File | 95 | __FUNCTION__; | Node\Scalar\MagicConst\Function_ | 96 | __LINE__; | Node\Scalar\MagicConst\Line | 97 | __METHOD__; | Node\Scalar\MagicConst\Method | 98 | __NAMESPACE__; | Node\Scalar\MagicConst\Namespace_ | 99 | __PROPERTY__; | Node\Scalar\MagicConst\Property | 100 | __TRAIT__; | Node\Scalar\MagicConst\Trait_ | 101 | 1.23; | Node\Scalar\Float_ | 102 | 123; | Node\Scalar\Int_ | 50
コードとノードの対応表 103 | "$a is not b."; | Node\Scalar\InterpolatedString |
104 | "a"; | Node\Scalar\String_ | 105 | class A { use B { a as c; } } | Node\Stmt\TraitUseAdaptation\Alias | 106 | class A { use B, C { C::d insteadof B; }} | Node\Stmt\TraitUseAdaptation\Precedence | 107 | { $a; $b; } | Node\Stmt\Block | 108 | break; | Node\Stmt\Break_ | 109 | switch($a) { case 1: break; } | Node\Stmt\Case_ | 110 | try {} catch (Exception $e) {} | Node\Stmt\Catch_ | 111 | class A { public const A = 1; } | Node\Stmt\ClassConst | 112 | class A { public function a() {} } | Node\Stmt\ClassMethod | 113 | class A {} | Node\Stmt\Class_ | 114 | const A = 1; | Node\Stmt\Const_ | 115 | continue; | Node\Stmt\Continue_ | 51
コードとノードの対応表 116 | declare(strict_types=1); | Node\Stmt\Declare_ | 117 | do
{} while ($a); | Node\Stmt\Do_ | 118 | echo "a"; | Node\Stmt\Echo_ | 119 | if ($a) {} elseif ($b) {} | Node\Stmt\ElseIf_ | 120 | if ($a) {} else {} | Node\Stmt\Else_ | 121 | enum A { case B; } | Node\Stmt\EnumCase | 122 | enum A {} | Node\Stmt\Enum_ | 123 | $a; | Node\Stmt\Expression | 124 | try {} finally {} | Node\Stmt\Finally_ | 125 | for (;;) {}; | Node\Stmt\For_ | 126 | foreach ($a as $b) {}; | Node\Stmt\Foreach_ | 127 | function a() {} | Node\Stmt\Function_ | 128 | global $a; | Node\Stmt\Global_ | 52
コードとノードの対応表 129 | goto a; a: | Node\Stmt\Goto_ | 130
| use A\{B, C}; | Node\Stmt\GroupUse | 131 | __halt_compiler(); | Node\Stmt\HaltCompiler | 132 | if ($a) {}; | Node\Stmt\If_ | 133 | ?>a | Node\Stmt\InlineHTML | 134 | interface A {} | Node\Stmt\Interface_ | 135 | a: | Node\Stmt\Label | 136 | namespace A; | Node\Stmt\Namespace_ | 137 | // | Node\Stmt\Nop | 138 | class A { public $a; } | Node\Stmt\Property | 139 | return; | Node\Stmt\Return_ | 140 | static $a; | Node\Stmt\Static_ | 141 | switch ($a) {}; | Node\Stmt\Switch_ | 53
コードとノードの対応表 142 | class A { use B; } |
Node\Stmt\TraitUse | 143 | trait A {} | Node\Stmt\Trait_ | 144 | try {} catch (E $e) {} | Node\Stmt\TryCatch | 145 | unset($a); | Node\Stmt\Unset_ | 146 | use A\B; | Node\Stmt\Use_ | 147 | while ($a) {}; | Node\Stmt\While_ | 148 | a($b); | Node\Arg | 149 | ["a"]; | Node\ArrayItem | 150 | #[A]class B{} | Node\Attribute | 151 | #[A, B]class B{} | Node\AttributeGroup | 152 | function() use ($a) {}; | Node\ClosureUse | 153 | const A = 1, B = 2; | Node\Const_ | 154 | declare(strict_types=1); | Node\DeclareItem | 54
コードとノードの対応表 155 | function a(int $b) {} | Node\Identifier |
156 | `a`; | Node\InterpolatedStringPart | 157 | function a(int&string $b) {} | Node\IntersectionType | 158 | match ($a) { 1 => 2 }; | Node\MatchArm | 159 | A; | Node\Name | 160 | function a(?int $b) {} | Node\NullableType | 161 | function a($b) {} | Node\Param | 162 | class A { public $b { get => $this->b; }} | Node\PropertyHook | 163 | class A { public $a, $c; } | Node\PropertyItem | 164 | static $a = 1; | Node\StaticVar | 165 | function a(int|string $b) {} | Node\UnionType | 166 | use A\{B}; | Node\UseItem | 167 | class A { public string $b; } | Node\VarLikeIdentifier | 55
コードとノードの対応表 168 | a(...); | Node\VariadicPlaceholder | 56
ちなみに 57
v4.14.0 とv5.3.1 の違いは 58
たくさんあるよ 詳しくはCHANGELOG[1]をみてね ただしノードに注目すると違いはほぼ PropertyHook が追加されたことだけ あといくつかのノードがリネームされたこと 59 1. https://github.com/nikic/PHP-Parser/blob/master/CHANGELOG.md
PropertyHook 60 https://www.php.net/manual/ja/language.oop5.property-hooks.php
PropertyHook 61 https://www.youtube.com/watch?v=N1UrFJElkow
PropertyHook 62 array( 0: Stmt_Class( attrGroups: array( ) flags: 0
name: Identifier( name: The ) extends: null implements: array( ) stmts: array( 0: Stmt_Property( attrGroups: array( ) flags: PUBLIC (1) type: Identifier( name: string ) props: array( 0: PropertyItem( name: VarLikeIdentifier( name: hand ) default: null ) ) hooks: array( 0: PropertyHook( attrGroups: array( ) flags: 0 byRef: false name: Identifier( name: get ) params: array( ) body: Expr_PropertyFetch( var: Expr_Variable( name: this ) name: Identifier( name: hand ) ) ) ) ) ) ) ) class The { public string $hand { get => $this->hand; } }
PropertyHook 63 3つのノードに注目。 • PhpParser\Node\Stmt\Class_ ノード • PhpParser\Node\Stmt\Property ノード •
PhpParser\Node\PropertyHook ノード
PropertyHook 64 class The { public string $world; public function
throwRoadRoller(){} } 文(statement)
PropertyHook 65 class The { public string $world; public function
throwRoadRoller(){} } 文(statement) Class_ノードは statementの配列を 保持する
PropertyHook 66 class The { public string $world; public function
throwRoadRoller(){} } 文(statement) Class_ノードは statementの配列を 保持する ちなみに ClassLikeが それを提供する
PropertyHook 67 class The { public string $world; public function
throwRoadRoller(){} } Stmt\ClassMethod Stmt\Property
PropertyHook 68 class The { public string $world; public function
throwRoadRoller(){} } Stmt\Property 従来のプロパティを 表す部分と
PropertyHook 69 class The { public string $world; public function
throwRoadRoller(){} } Stmt\Property 従来のプロパティを 表す部分と プロパティフックを 表す部分がある
PropertyHook 70 0: Stmt_Property( attrGroups: array() flags: PUBLIC (1) type:
Identifier( name: string ) props: array( 0: PropertyItem() ) hooks: array( 0: PropertyHook() ) ) Stmt\Property
PropertyHook 71 0: Stmt_Property( attrGroups: array() flags: PUBLIC (1) type:
Identifier( name: string ) props: array( 0: PropertyItem() ) hooks: array( 0: PropertyHook() ) ) 従来のプロパティを 表す部分 Stmt\Property
PropertyHook 72 0: Stmt_Property( attrGroups: array() flags: PUBLIC (1) type:
Identifier( name: string ) props: array( 0: PropertyItem() ) hooks: array( 0: PropertyHook() ) ) 従来のプロパティを 表す部分 プロパティフックを 表す部分 Stmt\Property
PropertyHook 73 class The { public string $hand { get
=> $this->hand; } }
PropertyHook 74 hooks: array( 0: PropertyHook( attrGroups: array() flags: 0
byRef: false name: Identifier( name: get ) params: array() body: Expr_PropertyFetch( var: Expr_Variable( name: this ) name: Identifier( name: hand ) ) ) )
PropertyHook 75 class The { public string $hand { get
=> $this->hand; } } コード ノード
PropertyHook 76
PropertyHook 77
以上 ノードの全体像と ノードとコードの対応関係 をみてきました 78
一度落ち着こう 79
まだあわてるような時間じゃない 80
このLTに込めた想い 私達はPHP Parserから大きな恩恵を受けています。 しかし、その事を気に留めることはほとんどないのではないでしょうか。 年に1度、5分だけ、1年分の感謝を込めてPHP Parserだけを見つめASTに想いを馳せる。 そんな時間にしたいと思います。 81 https://fortee.jp/phperkaigi-2025/proposal/a792f343-21f2-47fb-9e45-243a77dd57af
ありがとうPHP Parser Again, I wish to express my deep respect
and gratitude to PHP Parser 82
ありがとうnikic-san and nikic-san 83
84 ご清 盛聴ありがとうございました