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
270
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
97
Exploring Engineering in Workflow Development
inouehi
0
58
Using AI Tools Around Software Development
inouehi
0
1.5k
Learning Kotlin with detekt
inouehi
1
780
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
810
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
JETLS.jl ─ A New Language Server for Julia
abap34
2
460
AIコーディングエージェント(Gemini)
kondai24
0
300
Navigating Dependency Injection with Metro
l2hyunwoo
1
200
開発に寄りそう自動テストの実現
goyoki
2
1.5k
GISエンジニアから見たLINKSデータ
nokonoko1203
0
190
Findy AI+の開発、運用におけるMCP活用事例
starfish719
0
1.8k
リリース時」テストから「デイリー実行」へ!開発マネージャが取り組んだ、レガシー自動テストのモダン化戦略
goataka
0
150
AI Agent Tool のためのバックエンドアーキテクチャを考える #encraft
izumin5210
5
1.4k
The Art of Re-Architecture - Droidcon India 2025
siddroid
0
140
ThorVG Viewer In VS Code
nors
0
300
Combinatorial Interview Problems with Backtracking Solutions - From Imperative Procedural Programming to Declarative Functional Programming - Part 2
philipschwarz
PRO
0
120
LLMで複雑な検索条件アセットから脱却する!! 生成的検索インタフェースの設計論
po3rin
4
1k
Featured
See All Featured
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
65
35k
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
240
Un-Boring Meetings
codingconduct
0
170
Heart Work Chapter 1 - Part 1
lfama
PRO
3
35k
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
0
170
Building AI with AI
inesmontani
PRO
1
590
The innovator’s Mindset - Leading Through an Era of Exponential Change - McGill University 2025
jdejongh
PRO
1
72
Bash Introduction
62gerente
615
210k
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
115
95k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
1.7k
Rebuilding a faster, lazier Slack
samanthasiow
85
9.3k
Speed Design
sergeychernyshev
33
1.4k
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 ご清 盛聴ありがとうございました