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
170
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
Using AI Tools Around Software Development
inouehi
0
1.2k
Learning Kotlin with detekt
inouehi
1
530
Learning numeric-like string based on RFC
inouehi
0
92
What We Can Learn From OSS
inouehi
0
940
Learning PHP and Static Analysis with PHP Parser
inouehi
2
700
Understanding Ast By Looking
inouehi
0
2.1k
Improve Our Development Habits by Measuring Productivity and Maintainability
inouehi
1
1.5k
Simple Strategy to Read PHP More Easily
inouehi
0
820
What We Learned and What We Didn't from Our Efforts to Visualize Productivity
inouehi
0
580
Other Decks in Programming
See All in Programming
The Evolution of Enterprise Java with Jakarta EE 11 and Beyond
ivargrimstad
1
780
Cursor AI Agentと伴走する アプリケーションの高速リプレイス
daisuketakeda
1
120
GoのGenericsによるslice操作との付き合い方
syumai
2
650
業務自動化をJavaとSeleniumとAWS Lambdaで実現した方法
greenflagproject
1
120
Rails産でないDBを Railsに引っ越すHACK - Omotesando.rb #110
lnit
1
160
ReadMoreTextView
fornewid
1
450
既存デザインを変更せずにタップ領域を広げる方法
tahia910
1
230
GraphRAGの仕組みまるわかり
tosuri13
7
430
「ElixirでIoT!!」のこれまでとこれから
takasehideki
0
360
Java on Azure で LangGraph!
kohei3110
0
150
SODA - FACT BOOK
sodainc
1
1k
KotlinConf 2025 現地で感じたServer-Side Kotlin
n_takehata
1
220
Featured
See All Featured
The Pragmatic Product Professional
lauravandoore
35
6.7k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
26
2.8k
How STYLIGHT went responsive
nonsquared
100
5.6k
What’s in a name? Adding method to the madness
productmarketing
PRO
22
3.5k
Building Adaptive Systems
keathley
43
2.6k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
16
930
Faster Mobile Websites
deanohume
307
31k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
31
1.2k
Optimizing for Happiness
mojombo
379
70k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
228
22k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
4
190
Gamification - CAS2011
davidbonilla
81
5.3k
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 ご清 盛聴ありがとうございました