Upgrade to Pro — share decks privately, control downloads, hide ads and more …

夢の無限スパゲッティ製造機 #phperkaigi

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

夢の無限スパゲッティ製造機 #phperkaigi

Avatar for hideki kinjyo

hideki kinjyo PRO

March 22, 2026
Tweet

More Decks by hideki kinjyo

Other Decks in Technology

Transcript

  1. 自己紹介 • 金城秀樹 / きんじょうひでき • GitHub: @o0h / 𝕏

    : @o0h_ • 好きなスパゲッティはカルボナーラ • アイコンは美味しい鮭親子丼のChef ver.です • 最近はPodcastをやっています • ハッシュタグ: #readlinefm 18 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a
  2. おしながき 1. スパゲッティの世界と製造機の挑戦 2. 実演・基本的な処理 3. 実演・入り組んだ処理 4. 限界、そして言語の壁 5.

    最後に言いたいこと 19 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a
  3. 現代のプログラミングのパワー 25 スパゲッティつらい 節操ないgoto辛い 構造化プログラミング • 今より言語もハードも未成熟の時代、 「ジャンプ命令」でのロジック整理 • 複雑化・大規模化するにつれ、

    読解や保守の「キャパオーバー」 • 「構造化」でロジックを整理しやすく • for文やif文、function そして現代へ─ スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a
  4. 基礎文法 • gotoによって、指定された 場所までジャンプができる • ジャンプ先は「ラベル」を 指定する 30 スライド →

    https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a <?php goto C; A: echo "AʹདྷͨΑ\n"; exit(); B: echo "BʹདྷͨΑ\n"; goto A; C: echo "CʹདྷͨΑ\n"; goto B;
  5. 基礎文法 • gotoによって、指定された 場所までジャンプができる 31 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi

    #a <?php goto C; A: echo "AʹདྷͨΑ\n"; exit(); B: echo "BʹདྷͨΑ\n"; goto A; C: echo "CʹདྷͨΑ\n"; goto B; ラベル = 「文字列+コロン」 A: B: C:
  6. 基礎文法 32 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a <?php goto

    C; A: echo "AʹདྷͨΑ\n"; exit(); B: echo "BʹདྷͨΑ\n"; goto A; C: echo "CʹདྷͨΑ\n"; goto B; ジャンプ = 「goto+ラベル+セミコロン」 goto A; goto B;
  7. 基礎文法 33 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a <?php goto

    C; A: echo "AʹདྷͨΑ\n"; exit(); B: echo "BʹདྷͨΑ\n"; goto A; C: echo "CʹདྷͨΑ\n"; goto B; 最初にCにジャンプして
  8. 基礎文法 34 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a <?php goto

    C; A: echo "AʹདྷͨΑ\n"; exit(); B: echo "BʹདྷͨΑ\n"; goto A; C: echo "CʹདྷͨΑ\n"; goto B; C → Bに
  9. 基礎文法 35 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a <?php goto

    C; A: echo "AʹདྷͨΑ\n"; exit(); B: echo "BʹདྷͨΑ\n"; goto A; C: echo "CʹདྷͨΑ\n"; goto B; B → A
  10. 基礎文法 <?php goto C; A: echo "AʹདྷͨΑ\n"; exit(); B: echo

    "BʹདྷͨΑ\n"; goto A; C: echo "CʹདྷͨΑ\n"; goto B; Cに来たよ Bに来たよ Aに来たよ 36 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a <?php goto C; A: echo "AʹདྷͨΑ\n"; exit(); B: echo "BʹདྷͨΑ\n"; goto A; C: echo "CʹདྷͨΑ\n"; goto B;
  11. <?php goto C; A: echo "AʹདྷͨΑ\n"; exit(); B: echo "BʹདྷͨΑ\n";

    goto A; C: echo "CʹདྷͨΑ\n"; goto B; 基礎文法 <?php goto C; A: echo "AʹདྷͨΑ\n"; exit(); B: echo "BʹདྷͨΑ\n"; goto A; C: echo "CʹདྷͨΑ\n"; goto B; • ラベルは「ジャンプ先」に 指定ができるが、外からの 進入を防ぐものではない 37 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a <?php goto C; A: echo "AʹདྷͨΑ\n"; exit(); B: echo "BʹདྷͨΑ\n"; goto A; C: echo "CʹདྷͨΑ\n"; goto B; A → B → A → ・・・ と無限ループに陥るので、 Aの内側で離脱処理(exitなど)を 呼ぶ必要がある
  12. <?php $tmp0 = … sub: ————— goto hoge; end: アプローチ

    1. PHPで書かれたソースコードをインプットとして 2. いったんオペコードに変換し 3. 再びPHPの表現に戻す! 50 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a ソースコード オペコード <?php function hoge($x) { ————— } 0 INIT_FCALL 'hoge' 1 SEND_VAL 1 2 SEND_VAL 10 3 DO_ICALL $0 4 ECHO $0 5 RETURN 1 オペコード スパゲッティ
  13. • 「CV0にtrueを代入する」 <補足> オペコードってどんなもの? 55 boolのtrue ローカル変数 (CV0 = $iikanji)

    ASSIGN: 引数1に引数2を代入する スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a
  14. 帰りたい 80 goto today; echo 'end!!'; exit(); today: echo date('Y-m-d');

    関数を ひとかたまりの手続きに 名前をつけて呼び出すもの と捉える 関数(名)に対応する ラベルを作ってジャンプ? スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a
  15. 関数(名)に対応する ラベルを作ってジャンプ? 帰りたい 81 goto today; echo 'end!!'; exit(); today:

    echo date('Y-m-d'); これだと 元の位置に戻ってこれない ここに処理が来ない ✕ そのまま次の行へ スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a
  16. 帰りたい 82 goto today; return_1: echo 'endʂ'; exit(); today: echo

    date('Y-m-d'); goto return_1; 関数呼び出し後に 復帰する位置を設定し、 関数処理の最後にジャンプ スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a
  17. 帰りたい 83 today(); echo '---'; today(); echo 'endʂ'; 関数が 2回呼び出される時は?

    スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a
  18. 帰りたい 84 goto today; return_1: echo '---'; goto today; return_2:

    echo 'endʂ'; today: echo date('Y-m-d'); goto return_1; 関数が 2回呼び出される時は? さっきと同じく 復帰する位置を設定して ジャンプ? スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a
  19. さっきと同じく 復帰する位置を設定して ジャンプ? 帰りたい 85 goto today; return_1: echo '---';

    goto today; return_2: echo 'endʂ'; today: echo date('Y-m-d'); goto return_1; ここに処理が来ない ✕ 戻り先を決め打ちだと 対応できない!! スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a
  20. ちゃんと帰りたい 88 関数を呼び出す前に 「戻り先」を記録しておき $returnTo = 'return_1'; goto today; return_1:

    echo '---'; $returnTo = 'return_2'; return_2: echo 'endʂ'; exit(); スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a
  21. ちゃんと帰りたい 89 関数の最後は 「振り分けロジック」へと 飛ぶようにして today: echo date('Y-m-d'); goto return_1;

    goto return_dispatcher; スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a
  22. ちゃんと帰りたい 90 「戻り先」のメモに応じて 振り分けてジャンプ return_dispatcher: if ($returnTo === 'return_1') goto

    return_1; if ($returnTo === 'return_2') goto return_2; 力技で 飛び先となるラベルを全列挙★ スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a
  23. 返して欲しい コレ、どうしますか? 92 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a $date

    = today(); echo $date; function today() { return date('Y-m-d'); } 値を受け取って 変数に代入
  24. 返して欲しい 返り値用の専用変数を作る。 呼び出し元・呼び出し先で 同じ変数を読み書きする 93 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi

    #a $returnTo = 'return_1'; goto today; return_1: $today = $returnVal; echo $today; exit(); today: $returnVal = date('Y-m-d'); goto return_dispatcher; グローバル変数、 最高〜!
  25. 呼びたい コレ、どうしますか? 95 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a function

    countDown() { $days = calcDays(); return "͋ͱ{$days}೔!!"; } function calcDays() { $kaigi = strtotime('3/20'); return date('z', $kaigi) - date('z'); } echo countDown();
  26. 呼びたい 先程の例で導入した 戻り先の振り分けを使うと こんな感じに 96 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi

    #a $returnTo = 'return_1'; goto countDown; return_1: echo $returnVal; exit(); countDown: $returnTo = 'return_2'; goto calcDays; return_2: $returnVal = "͋ͱ{$returnVal}೔!!"; goto return_dispatcher; calcDays: $kaigi = strtotime('3/20'); $returnVal = date('z', $kaigi) - date('z'); goto return_dispatcher;
  27. 呼びたい 制御フローだけ抜き出すと こんな感じ 97 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a

    $returnTo = 'return_1'; goto countDown; return_1: exit(); countDown: $returnTo = 'return_2'; goto calcDays; return_2: goto return_dispatcher; calcDays: goto return_dispatcher;
  28. 呼びたい $returnToを使い回す。 「直近の1つ」しか 戻り先を保持できない 98 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi

    #a $returnTo = 'return_1'; goto countDown; return_1: exit(); countDown: $returnTo = 'return_2'; goto calcDays; return_2: goto return_dispatcher; calcDays: goto return_dispatcher; 呼び出し先の関数内で 上書きされてしまう
  29. 呼びたい 99 $returnTo = 'return_1'; goto countDown; return_1: exit(); countDown:

    $returnTo = 'return_2'; goto calcDays; return_2: goto return_dispatcher; calcDays: goto return_dispatcher; 永久に return_2から 抜け出せない $returnToを使い回す。 「直近の1つ」しか 戻り先を保持できない ✕ スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a
  30. 呼びたい 100 $returnTo = 'return_1'; goto countDown; return_1: exit(); countDown:

    $returnTo = 'return_2'; goto calcDays; return_2: goto return_dispatcher; calcDays: goto return_dispatcher; 複数の戻り先を管理したい 「階層」の概念の導入 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a
  31. 呼びたい 101 $stackLevel = 0; $stackLevel++; $returnTo[$stackLevel] = 'return_1'; goto

    countDown; 「現在の階層」を管理して スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a
  32. 呼びたい 102 $stackLevel = 0; $stackLevel++; $returnTo[$stackLevel] = 'return_1'; goto

    countDown; 関数へのジャンプ前 (=「次に進む」前)に インクリメントする スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a
  33. 呼びたい 103 $stackLevel = 0; $stackLevel++; $returnTo[$stackLevel] = 'return_1'; goto

    countDown; 戻り先を 対応する階層と紐づけて 複数レベルで管理する スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a
  34. 呼びたい 104 $returnTo = [ 0 => 'return_1', 1 =>

    'return_2', ]; 今いる階層に応じて、 return_dispatcherが 戻り先を区別できるように スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a
  35. 呼びたい 105 return_dispatcher: $stackLevel--; if ($returnTo[$stackLevel] === 'return_1') goto return_1;

    if ($returnTo[$stackLevel] === 'return_2') goto return_2; return_dispatcherで、 「戻り先に戻す」直前で 階層レベルを引き下げておく スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a
  36. 呼びたい 106 // $returnTo = 'return_1'; countDown: $returnTo = 'return_2';

    goto calcDays; return_2: goto return_dispatcher; calcDays: goto return_dispatcher; 永久に return_2から 抜け出せない さっきまでの状況 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a
  37. 呼びたい 107 // $returnTo[$stackLevel] // = 'return_1' countDown: $stackLevel++; $returnTo[$stackLevel]

    = 'return_2'; goto calcDays; return_2: goto return_dispatcher; calcDays: goto return_dispatcher; leve=0なので、 return_1に戻る 新しい状況 leve=1なので、 return_2に戻る スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a
  38. 混ざりたくない 110 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a $v =

    14; echo foo($v); function foo($v): float { $rate = 1.05; return $v * $rate; } 関数の外の変数と 名前が被っているけど 区別しなくてはいけない
  39. 混ざりたくない 呼び出し側: 引数の位置ごとに、 階層と値をマッピングした 辞書を作成する 112 スライド → https://20260322.nichiyou.be ハッシュタグ

    →#phperkaigi #a $v = 14; $stackLevel++; $arg0[$stackLevel] = $v; $returnTo[$stackLevel] = 'return_1'; goto foo; return_1: echo $returnVal; exit(); $v = 1; echo foo($v);
  40. 混ざりたくない 関数側: 引数の辞書から 「ローカル変数」に写して 処理を進める 113 スライド → https://20260322.nichiyou.be ハッシュタグ

    →#phperkaigi #a foo: $paramFuncFoo_v = $arg0[$stackLevel]; // $rateΛνΣοΫͯ͠ॳظԽ; $rate[$stackLevel] = 1.05; $returnVal = $paramFuncFoo_v * $rate[$stackLevel]; goto return_dispatcher; function foo($v) { $rate = 1.05; return $v * $rate; }
  41. 混ざりたくない 関数側: 通常のローカル変数も 「何階層目で呼ばれたか」 を管理する 114 スライド → https://20260322.nichiyou.be ハッシュタグ

    →#phperkaigi #a foo: $paramFuncFoo_v = $arg0[$stackLevel]; // $rateΛνΣοΫͯ͠ॳظԽ; $rate[$stackLevel] = 1.05; $returnVal = $paramFuncFoo_v * $rate[$stackLevel]; goto return_dispatcher; function foo($v) { $rate = 1.05; return $v * $rate; }
  42. goto ??? <§3後編: 実演Ⅱ・入り組んだ処理> 1. クラスの基本的な話(プロパティやメソッドの表現) 2. `$this` ってどうやってるの? <§4:

    限界、そして言語の壁> 1. 組み込みクラス 2. オペコード上に表れてこないデータ 3. 対応が難しそうで見送っているもの <それ以外> 1. 継承やinstanceofの再現 118 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a
  43. 初めてのclass クラスを、基本的に「データ」「手続き」の集合であるとみなしてみる 1. プロパティ = 連想配列のキーと値みたいなもの 2. メソッド = goto

    + return_dispatcherを使った手続きみたいなもの 121 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a
  44. まとめたい 例えばこんなの 122 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a class

    Foo { public $v; public function get7X() { return $this->v * 7; } } $foo = new Foo(); $foo->v = 1111; echo $foo->get7X();
  45. まとめたい 基本的な構造はこうなる 123 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a $foo

    = ['class' => 'Foo']; $foo['v'] = 1111; $stackLevel++; $returnTo[$stackLevel] = 'return_1'; goto Foo_get7x; $foo = new Foo(); $foo->v = 1111; echo $foo->get7X();
  46. $foo = new Foo(); $foo->v = 1111; echo $foo->get7X(); まとめたい

    インスタンス化 = クラス情報を与えた配列 124 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a $foo = ['class' => 'Foo']; $foo['v'] = 1111; $stackLevel++; $returnTo[$stackLevel] = 'return_1'; goto Foo_get7x;
  47. $foo = new Foo(); $foo->v = 1111; echo $foo->get7X(); まとめたい

    プロパティへの代入 = 連想配列へのセット 125 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a $foo = ['class' => 'Foo']; $foo['v'] = 1111; $stackLevel++; $returnTo[$stackLevel] = 'return_1'; goto Foo_get7x;
  48. $foo = new Foo(); $foo->v = 1111; echo $foo->get7X(); まとめたい

    メソッド呼び出し = gotoでのジャンプ 126 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a $foo = ['class' => 'Foo']; $foo['v'] = 1111; $stackLevel++; $returnTo[$stackLevel] = 'return_1'; goto Foo_get7x;
  49. $thisしたい もちろん、 これだと問題がある 129 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a

    Foo_get7x: $returnVal = $this->v * 7; goto return_dispatcher; public function get7X() { return $this->v * 7; } 😠
  50. $thisしたい 呼び出し側: 生成したインスタンスごとに 固有のIDを用意し、 IDを使ってオブジェクトを参 照できるようにする 132 スライド → https://20260322.nichiyou.be

    ハッシュタグ →#phperkaigi #a // ॳظԽ $objects = []; $objIdCounter = 0; $_this = []; $objIdCounter++; $objects[$objIdCounter] = [ 'class' => 'Foo', ]; $objects[$objIdCounter]['v'] = 1111; 生成(new Class)する度に インクリメント
  51. $thisしたい 呼び出し側: 生成したインスタンスごとに 固有のIDを用意し、 IDを使ってオブジェクトを参 照できるようにする 133 スライド → https://20260322.nichiyou.be

    ハッシュタグ →#phperkaigi #a // ॳظԽ $objects = []; $objIdCounter = 0; $_this = []; $objIdCounter++; $objects[$objIdCounter] = [ 'class' => 'Foo', ]; $objects[$objIdCounter]['v'] = 1111; IDを使って インスタンス管理
  52. $thisしたい 呼び出し側: メソッドへのジャンプ前に、 $thisという配列で、 インスタンスIDを 今から使う階層にマッピング 134 スライド → https://20260322.nichiyou.be

    ハッシュタグ →#phperkaigi #a $stackLevel++; $returnTo[$stackLevel] = 'return_1'; $this[$stackLevel] = $objIdCounter; goto Foo_get7x; 引数と同じノリ。 「階層に閉じた値」となる
  53. $thisしたい 関数側: 現在の階層の情報を用いて、 オブジェクト(ID)マップから 自インスタンスでのthisに当 たるデータを取得する 135 スライド → https://20260322.nichiyou.be

    ハッシュタグ →#phperkaigi #a Foo_get7x: $tmpObjectId = $this[$stackLevel]; $tmpThis = $objects[$tmpObjectId]; $returnVal = $tmpThis['v'] * 7; goto return_dispatcher;
  54. $thisしたい 136 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a Foo_get7x: $tmpObjectId

    = $this[$stackLevel]; $tmpThis = $objects[$tmpObjectId]; $returnVal = $tmpThis['v'] * 7; goto return_dispatcher; 今のコンテキストでの オブジェクトのIDを取得
  55. $thisしたい 137 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a Foo_get7x: $tmpObjectId

    = $this[$stackLevel]; $tmpThis = $objects[$tmpObjectId]; $returnVal = $tmpThis['v'] * 7; goto return_dispatcher; そのIDに紐づいている データを取得
  56. $thisしたい 138 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a Foo_get7x: $tmpObjectId

    = $this[$stackLevel]; $tmpThis = $objects[$tmpObjectId]; $returnVal = $tmpThis['v'] * 7; goto return_dispatcher; あとはそのまま参照すればOK
  57. クラスの例 new や メソッドコールを ヘルパーを介して実行する 145 スライド → https://20260322.nichiyou.be ハッシュタグ

    →#phperkaigi #a $d = __builtin_new('D', []); $x = __builtin_call( $d, 'format', ['c'] ); echo __builtin_unwrap($x);
  58. 定数配列 • 次のコードのオペコードを生成すると、 • 通常は、このように配列の中身が現れない • 夢の無限スパゲッティ製造機だと、こうなる $config1 = ['name'

    => 'test', 'value' => 42]; L0003 0000 ASSIGN CV0($config) array(...) 3: ASSIGN CV0($config1) "[\'name\' => \'test\',\'value\' => 42]" 148 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a
  59. "=", [397, " ", 2], "[", [269, "'name'", 2], [397,

    " ", 2], [391, "=>", 2], [397, " ", 2], [269, "'test'", 2], ",", [397, " ", 2], [269, "'value'", 2], [397, " ", 2], [391, "=>", 2], [397, " ", 2], token_get_allの結果 (説明用に整形しています)
  60. "=", [397, " ", 2], "[", [269, "'name'", 2], [397,

    " ", 2], [391, "=>", 2], [397, " ", 2], [269, "'test'", 2], ",", [397, " ", 2], [269, "'value'", 2], [397, " ", 2], [391, "=>", 2], [397, " ", 2], 0:トークンの識別ID 1: ソース 2: 行番号
  61. "=", [397, " ", 2], "[", [269, "'name'", 2], [397,

    " ", 2], [391, "=>", 2], [397, " ", 2], [269, "'test'", 2], ",", [397, " ", 2], [269, "'value'", 2], [397, " ", 2], [391, "=>", 2], [397, " ", 2], array(…)があった 「2行目」のトークンを探して
  62. "=", [397, " ", 2], "[", [269, "'name'", 2], [397,

    " ", 2], [391, "=>", 2], [397, " ", 2], [269, "'test'", 2], ",", [397, " ", 2], [269, "'value'", 2], [397, " ", 2], [391, "=>", 2], [397, " ", 2], array の開始位置を見つけたら
  63. "=", [397, " ", 2], "[", [269, "'name'", 2], [397,

    " ", 2], [391, "=>", 2], [397, " ", 2], [269, "'test'", 2], ",", [397, " ", 2], [269, "'value'", 2], [397, " ", 2], [391, "=>", 2], [397, " ", 2], そこから「配列の中身」を抜き出す = "[" と "]" の間のトークン
  64. "=", [397, " ", 2], "[", [269, "'name'", 2], [397,

    " ", 2], [391, "=>", 2], [397, " ", 2], [269, "'test'", 2], ",", [397, " ", 2], [269, "'value'", 2], [397, " ", 2], [391, "=>", 2], [397, " ", 2], ['name' => 'test', 'value' => 42]
  65. include/requireの(完全な)対応 〜それでも〜 • `include $file` のようなコードはComposerのautoloadでも出てくる • 夢の無限スパゲッティ製造機はComposerの夢を見るか? • →はい、見ます

    • 別のアプローチで対応の実装済み • 気になる人はQ&AかAsk The Speakerで聞いてください 163 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a
  66. 発表では触れていないけど、こんなコードも行けます 気になるものがあったら、Ask The Speakerや懇親会でもどうぞ! ※ 上手く答えられるかはモノによります • クラスの継承 • try-catch-finally

    • 可変長引数・名前付き引数 • ジェネレータ(yield) ※一部非対応 • 無名関数・無名クラス 167 スライド → https://20260322.nichiyou.be ハッシュタグ →#phperkaigi #a
  67. おまけ • なんやかんやで、 Slimを使ったアプリケーションの スパゲッティ化に成功しました • →のコードが変換元(32行) => 53,957行 •

    github.com/o0h/the-spaghetti-dream-gallery を見てみてください • 僕は怖くて中身を見ていません • ただし変換前後のコードに対して 同じ内容のE2Eテストはパス済み(thx runn!) スライド → https://20260322.nichiyou.be 168 ハッシュタグ →#phperkaigi #a