Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
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
230
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
Exploring Engineering in Workflow Development
inouehi
0
37
Using AI Tools Around Software Development
inouehi
0
1.5k
Learning Kotlin with detekt
inouehi
1
680
Learning numeric-like string based on RFC
inouehi
0
110
What We Can Learn From OSS
inouehi
0
1.1k
Learning PHP and Static Analysis with PHP Parser
inouehi
2
760
Understanding Ast By Looking
inouehi
0
2.2k
Improve Our Development Habits by Measuring Productivity and Maintainability
inouehi
1
1.6k
Simple Strategy to Read PHP More Easily
inouehi
0
850
Other Decks in Programming
See All in Programming
チームの境界をブチ抜いていけ
tokai235
0
230
Google Opalで使える37のライブラリ
mickey_kubo
3
150
CSC509 Lecture 07
javiergs
PRO
0
250
20251016_Rails News ~Rails 8.1の足音を聴く~
morimorihoge
3
860
Server Side Kotlin Meetup vol.16: 内部動作を理解して ハイパフォーマンスなサーバサイド Kotlin アプリケーションを書こう
ternbusty
3
260
CSC509 Lecture 08
javiergs
PRO
0
260
はじめてのDSPy - 言語モデルを『プロンプト』ではなく『プログラミング』するための仕組み
masahiro_nishimi
4
16k
Cursorハンズオン実践!
eltociear
2
1.2k
Developer Joy - The New Paradigm
hollycummins
1
380
What's new in Spring Modulith?
olivergierke
1
170
オンデバイスAIとXcode
ryodeveloper
0
260
Reactive Thinking with Signals and the Resource API
manfredsteyer
PRO
0
120
Featured
See All Featured
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
34
2.3k
Agile that works and the tools we love
rasmusluckow
331
21k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
5.7k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
15k
Site-Speed That Sticks
csswizardry
13
930
4 Signs Your Business is Dying
shpigford
186
22k
The Power of CSS Pseudo Elements
geoffreycrofte
80
6k
How to train your dragon (web standard)
notwaldorf
97
6.3k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
253
22k
jQuery: Nuts, Bolts and Bling
dougneiner
65
7.9k
Code Review Best Practice
trishagee
72
19k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
23
1.5k
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 ご清 盛聴ありがとうございました