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

#phperkaigi 作って遊ぼう!Composer Plugin

#phperkaigi 作って遊ぼう!Composer Plugin

PHPerKaigi2022での資料です。
https://fortee.jp/phperkaigi-2022/proposal/cc3f627d-4268-455e-9faf-fe7194a0c343

セッションでの発表時に利用していたものに加筆・修正したものになります。

- 一部のスライドの構成、表現などの変更
- Appendixの追加

hideki kinjyo
PRO

April 10, 2022
Tweet

More Decks by hideki kinjyo

Other Decks in Programming

Transcript

  1. 作って遊ぼう!
    Composer Plugin
    PHPerKaigi 2022
    Hideki Kinjyo
    GitHub: o0h / Twitter: @o0h_
    [഑෍൛]

    View Slide

  2. PHPer͸ComposerʹٹΘΕ·ͨ͠
    ͋Γ͕ͱ͏໊લۭؒɺ͋Γ͕ͱ͏Φʔτϩʔυ
    • 2006೥ / PHP5.1.2: spl_autoload_registerͷࢥ͍ग़
    • 2009೥ / PHP5.3.0: ॳΊͯͷ໊લۭؒͷࢥ͍ग़
    • 2009೥: PHP Standards GroupͱPSR-0ͷࢥ͍ग़
    • 2010೥: SplClassLoader(RFC)ͷࢥ͍ग़

    View Slide

  3. PHPer͸ComposerʹٹΘΕ·ͨ͠
    • 2011೥: Composer/Packagist։ൃ։࢝
    • 2012೥3݄: Composer 1.0.0-alpha1
    2012೥3݄

    View Slide

  4. PHPer͸ComposerʹٹΘΕ·ͨ͠
    • 2011೥: Composer/Packagist։ൃ։࢝
    • 2012೥3݄: Composer 1.0.0-alpha1
    ᴷ͋Γ͕ͱ͏ɺ$PNQPTFSɻࡀ͓ΊͰͱ͏ʂ
    ೥݄ͷ1)1FSTΑΓ

    View Slide

  5. メモリアルイヤーだ!
    ComposerにSponsoringしませんか!
    お世話になっているOSSに直接的なお礼をしよう

    View Slide

  6. GitHubからどうぞ!
    https://github.com/sponsors/composer

    View Slide

  7. アイコンと名前を載せましょう
    カンタンカンタン。コワクナイヨ

    View Slide

  8. ࣗݾ঺հ
    • ⾦城秀樹 / きんじょうひでき
    • GitHub: @o0h / Twitter: @o0h_
    • 好きなFWはCakePHP
    • アイコンは
    美味しい鮭親⼦丼の写真です

    View Slide

  9. §0
    イントロ

    View Slide

  10. ComposerͬͯͳΜ͚ͩͬ
    ໾ׂͰߟ͑ͯΈΔͱɺComposerͱ͸ɾɾɾ
    • ϓϩδΣΫτ(≒ύοέʔδͷू߹ମ)ͷ؅ཧπʔϧͰ͋Γ
    • ґଘ(ύοέʔδ)ͷ؅ཧπʔϧͰ΋͋Γ
    • λεΫϥϯφʔͱ΋ݴ͑Δ

    View Slide

  11. As ϓϩδΣΫτͷ؅ཧπʔϧ
    • composer.jsonʹɺඞཁ
    ͳύοέʔδ৘ใ͕શͯ
    ू໿͞Ε͍ͯΔ
    • ͦΕҎ֎ʹ΋ɺϓϩδΣ
    Ϋτͷϝλ৘ใΛѻ͏͜
    ͱ͕ग़དྷΔ
    •͢ͳΘͪϓϩδΣΫτͷ
    ʮఆٛʯʮ૊ΈཱͯʯΛ
    ୲͍ͬͯΔ

    View Slide

  12. As ґଘ(ύοέʔδ)ͷ؅ཧπʔϧ
    • ඞཁͳύοέʔδͷ
    औಘɾ഑ஔɺߋ৽Λߦ
    ͏ػೳΛఏڙ
    • ద੾ͳऔಘઌͷ൑அ
    ΍֤ݸͷύοέʔδͷ
    ཁٻΛղܾ͢Δ

    View Slide

  13. As λεΫϥϯφʔ
    • Α͘࢖͏λεΫΛొ
    ࿥ɾ؅ཧͯ͠ɺ؆୯ʹ
    ݺͼग़ͤΔΑ͏ʹ͢Δ
    • PHPͷॲཧʹݶΒͣɺ
    shellͦͷଞͷݺͼग़͠
    ΋Ͱ͖Δ

    View Slide

  14. Composerは「⾊々できる」「⾊々な情報を持っている」
    => コレを活かして、
    更に⾃由に振るまえるように出来る仕組みが「Plugin」

    View Slide

  15. うまく付き合えば
    私の/あなたのPJの
    「煩雑な所」がスッキリするかもね!?
    っていう便利系のやつの紹介です
    ຊηογϣϯΛ
    ҰݴͰ͓఻͑͢Δͱ

    View Slide

  16. ͓͠ͳ͕͖
    1.ຊ౰ʹ͋ͬͨʂComposer Plugin ʙ࣮ྫἫʙ
    2. ֓આ: Composer Plugin
    3. ͘͢͝؆୯ͳPluginͷ࣮૷ྫ
    4. ৭ʑͳPluginͷத਎ΛงғؾͰಡΜͰΈΔ
    時間に余裕があれば!

    View Slide

  17. §1
    本当にあった!
    Composer Plugin 〜実例篇〜

    View Slide

  18. Packagist
    type: composer-pluginでプラグインを探せる

    View Slide

  19. 有名どころや、
    効果がわかりやすそうなものを
    いくつか取り上げて紹介(私選)

    View Slide

  20. composer require symfony/thanks
    { ֦ுϙΠϯτ: ಠࣗͷίϚϯυΛ௥Ճ͢Δ }
    • `composer thanks`ͱ͍͏ίϚϯυΛ௥Ճ
    • ͋ͳͨͷϓϩδΣΫτͰ͓ੈ࿩ʹͳ͍ͬͯΔύοέʔδʹ
    GitHubͷελʔΛૹͬͯ͘ΕΔʂ

    View Slide

  21. UIBOLTͱ͍͏ಠࣗίϚϯυ͕௥Ճ͞Εɺ
    ࣮ߦ͢Δͱ(JU)VCϨϙδτϦʹ˒Λ෇͚Δ

    View Slide

  22. ࣮ࡍʹ˒͕͍͍ͭͯΔ༷ࢠ

    View Slide

  23. composer require phpstan/extension-installer
    { 拡張ポイント: パッケージの追加時の挙動を追加する }
    • PHPStanのextensionがrequire/update時に、
    ⾃動的にプラグインを有効化
    • PHPStanが読み込みに⾏くように設定ファイルに追記
    • 設定ファイルを⼿動でいじる必要がなくなる!

    View Slide

  24. UZQFQIQTUBOFYUFOTJPOͳύοέʔδͷಋೖʹ൓Ԡͯ͠ɺ
    ઃఆϑΝΠϧͷߋ৽Λߦ͏

    View Slide

  25. UZQFQIQTUBOFYUFOTJPOͳύοέʔδͷಋೖʹ൓Ԡͯ͠ɺ
    ઃఆϑΝΠϧͷߋ৽Λߦ͏

    View Slide

  26. UZQFQIQTUBOFYUFOTJPOͳύοέʔδͷಋೖʹ൓Ԡͯ͠ɺ
    ઃఆϑΝΠϧͷߋ৽Λߦ͏

    View Slide

  27. ࣮ࡍʹు͖ग़͞ΕΔྫ

    View Slide

  28. composer require bamarni/composer-bin-plugin
    { ֦ுϙΠϯτ: Πϯετʔϧͷઓུ(ϑΝΠϧͷ഑ஔઌ)Λมߋ͢Δ }
    • ։ൃܥͷπʔϧ(౳)Λɺ௨ৗͷvendorͱ͸ผͷ৔ॴʹ഑ஔ͢Δ
    • ؒ઀తʹґଘ͢Δύοέʔδ౳ͷίϯϑϦΫτΛղফ͢Δ
    • ʮϓϩμΫτίʔυͱlinterπʔϧͰཁٻ͢Δόʔδϣϯ͕ҧ
    ͏ʂʯͱ͍ͬͨ࣌ʹ΋ɺʮͦΕͧΕ͕ඞཁͳґଘόʔδϣϯΛ
    ֬อ͢Δʯ͜ͱ͕Ͱ͖Δ

    View Slide

  29. 1IBO 1IQ.FUSJDTΛִ཭ͯ͠Πϯετʔϧ

    View Slide

  30. 1IBO 1IQ.FUSJDTΛִ཭ͯ͠Πϯετʔϧ

    View Slide

  31. 1IBO 1IQ.FUSJDTΛִ཭ͯ͠Πϯετʔϧ

    View Slide

  32. 指定した名前空間ごとに、別個
    のvendorディレクトリが作成さ
    れる
    通常のvendor/bin以下に、
    vendor-binディレクトリ以下の
    実ファイルにproxyする実⾏ファ
    イルが作成される
    これにより、名前空間を気にせ
    ずにbinファイルを実⾏可能に

    View Slide

  33. といった感じで、
    Composer利⽤時の⾊々なトリガーや
    独⾃のコマンドの追加によって
    ⾊々な処理を噛ませられる!!
    のがPluginの機能です

    View Slide

  34. §2
    概説: Composer Plugin

    View Slide

  35. ݁ہͳΜͳͷͰ͔͢ʁ
    doc: https://getcomposer.org/doc/articles/plugins.md
    • “You may wish to alter or expand Composer's
    functionality with your own.”
    • “In these cases you could consider creating a plugin to
    handle your specific logic.”
    意訳: 君だけのComposerロジックを⼿に⼊れろ!

    View Slide

  36. Ͳ͏࣮ݱͯ͠ɺԿ͕Ͱ͖ΔͷͰ͔͢ʁ
    ओʹ2ͭͷhook͕͋Γɺͦ͜ʹҾֻ͚ͬͯಠࣗॲཧΛೖΕࠐΉ
    1. ಠࣗCommandΛొ࿥͠ɺར༻͢Δॲཧ
    2. Composer͕ൃߦ͍ͯ͠ΔΠϕϯτͷߪಡʹΑΔॲཧ
    ͦΕͧΕͷํ๏΍λΠϛϯάͰɺ
    ComposerͷίϯςΩετΛར༻ͨ͠ॲཧΛڬΉ͜ͱ͕Ͱ͖Δ

    View Slide

  37. ಠࣗίϚϯυͷొ࿥
    { Capability }
    Plugin͔ΒɺComposerʹରͯ͠
    ʮར༻ՄೳͳίϚϯυҰཡͷऔಘํ
    ๏ʯΛڞ༗͢Δɻ
    `Capable::getCapabilities():
    array`
    ͷ࣮૷
    ྫ: bamarni/composer-bin-plugin
    ࢀߟ
    4FUUJOHVQBOEVTJOHQMVHJOT$PNQPTFS
    IUUQTHFUDPNQPTFSPSHEPDBSUJDMFTQMVHJOTNEQMVHJO
    DBQBCJMJUJFT

    View Slide

  38. Plugin
    Composer
    プラグイン本体
    <Interface>
    Capable
    プラグインを
    読み込むよ!
    お、Capability持ってるな
    独⾃のコマンドを
    提供できます!
    詳しくは
    プロバイダを参照!
    <Interface>
    CommandProvider
    プロバイダ
    どんなコマンド
    ある?
    コマンドの
    ⼀覧です!
    <Interface>
    PluginInterface
    コマンド
    Command
    DO COMMAND!
    I DO!

    View Slide

  39. ऄ଍: Command?
    ComposerͷCommand͸
    symfony/consoleΛར༻͍ͯ͠·͢ɻ
    աڈʹComposerͷ಺෦ߏ଄ʹ͍ͭ
    ͯͷൃදΛ͓ͯ͠Γ·͢ͷͰɺ͝ڵ
    ຯ͋Γ·ͨ͠Βޚཡ͍ͩ͘͞
    ࢀߟ
    $PNQPTFSͬͯԿʁͲ͏ಈ͘ͷʁಡΜͰΈ·ͨ͠ʂ
    IUUQTTQFBLFSEFDLDPNPIMFUTSFBEDPNQPTFS TMJEF

    View Slide

  40. Πϕϯτ΁ͷhookͷར༻
    { ग़൛-ߪಡܕϞσϧ }
    PluginຊମͷதͰɺ
    Πϕϯτ㱻ରԠ͢Δॲཧͷ
    ؔ࿈෇͚Λߦ͏ɻ
    `EventSubscriberInterface:
    :getSubscribedEvents():
    array`
    ͷ࣮૷
    ྫ: phpstan/extension-installer

    View Slide

  41. Plugin
    Composer
    プラグイン本体
    <Interface>
    EventSubscriberInterface
    プラグインを
    読み込むよ!
    お、Subscriberだな
    <Interface>
    PluginInterface
    何を購読してる?
    購読の⼀覧です!
    処理
    イベント発⽕
    それ購読してる!
    I DO SOMETHING!

    View Slide

  42. コマンドの
    前処理に⼊るよ!
    その前に○○が使えるか
    チェックして!
    イベント プラグイン
    パッケージの
    meta情報をDLしたよ!
    ライセンスを
    確認して!
    パッケージの
    インストールを
    完了したよ!
    tests以下は削除して!
    レポジトリ情報を
    取得するよ!
    VPN有効?
    サーバー接続確認して!
    ྫ: Πϕϯτ㲗ϓϥάΠϯͰ৭ʑͳֻ͚߹͍͕Ͱ͖Δͷਤ
    .lockファイルを
    書き込んだよ!
    minifyして!

    View Slide

  43. ͲΜͳΠϕϯτ͕͋ΔͷͰ͔͢ʁ
    • େ·͔ʹ4ܥ౷ͷΠϕϯτ͕͋Δ
    • Plugin Events / Command Events / Package Events /
    Installer Events
    • Πϕϯτ͸ͦΕͧΕʹԠͨ͡ίϯςΩετ৘ใΛؚ༗ͯ͠
    ͓ΓɺϦεφ͸ͦΕΒͷ৘ใͱCompoerΦϒδΣΫτɾIO
    ΦϒδΣΫτΛ૊Έ߹Θͤͯ೚ҙͷॲཧΛ࣮૷͢Δ
    ࢀߟ
    &WFOUOBNFT
    IUUQTHFUDPNQPTFSPSHEPDBSUJDMFTTDSJQUTNEFWFOUOBNFT

    View Slide

  44. 1. Plugin Events
    ComposerͷجװΛ୲͏ॲཧͱͰ΋ݴ͏΂͖λΠϛϯάʹൃՐ͞ΕΔ
    { ओͳΠϕϯτ }
    ComposerΦϒδΣΫτͷॳظԽɺCommandͷॳظԽɺϑΝΠϧͷDLલޙͳͲ
    { ओͳίϯςΩετ }
    ʮϑΝΠϧͷμ΢ϯϩʔυલʯͰ͋Ε͹ʮऔಘઌͷURL৘ใʯɺʮCommandͷ
    ࣮ߦલ(ॳظԽத)ʯͰ͋Ε͹ʮೖྗ৘ใʯͱ͍ͬͨίϯςΩετΛѻ͑Δ
    ※ ϓϥάΠϯ಺෦΍ؔ࿈ॲཧʹ͍ͭͯͷΠϕϯτͱ͍͏ࣄͰ͸ͳ͘ɺ
    ʮϓϥάΠϯͱ͍͏ར༻ऀͷͨΊʹ༻ҙ͞ΕͨΠϕϯτͱ͍͏ػߏͷ͏ͪɺҰൠతͳ΋ͷʯΈ͍ͨͳχϡΞϯεͳͷͩ
    ͱࢥ͍·͢

    View Slide

  45. 2. Command Events
    Composerͷ࣋ͭ(ඪ४)ίϚϯυͷ࣮ߦલޙʹൃՐ͞ΕΔ
    { ओͳΠϕϯτ }
    ʮinstallʯʮupdateʯʮdumpautoloadʯʮcreate-projectʯͳͲͷ
    ComposerίϚϯυͷ࣮ߦલɾ࣮ߦޙ
    { ओͳίϯςΩετ }
    ʮίϚϯυ໊ʯʮinput/outputʯʮ࣮ߦ࣌ύϥϝʔλͱ͍ͬͨίϯ
    ςΩετΛѻ͑Δ

    View Slide

  46. 3. Package Events
    ύοέʔδݸผͷల։΍഑ஔɺআڈͷલޙʹൃՐ͞ΕΔ
    { ओͳΠϕϯτ }
    ֤ύοέʔδʹର͢Δʮinstallʯʮupdateʯʮremoveʯͷ࣮ߦલɺ
    ࣮ߦޙ
    { ओͳίϯςΩετ }
    ର৅ύοέʔδ৘ใ(໊લɾόʔδϣϯetc)ɺૢ࡞಺༰(৽͘͠ஔ͘ͷ
    ͔ɺߋ৽͢Δͷ͔ɺআڈ͢Δͷ͔)ͱ͍ͬͨίϯςΩετΛѻ͑Δ
    ※ల։ = ΞʔΧΠϒͷղౚɺ഑ஔ = vendorσΟϨΫτϦԼ΁ͷҠಈ

    View Slide

  47. 4. Installer Events
    ύοέʔδશମͷ഑ஔ࣮ߦલʹൃՐ͞ΕΔ
    { ओͳΠϕϯτ }
    ಛఆ͞Εͨύοέʔδͷऔಘ΍഑ஔͷલ
    { ओͳίϯςΩετ }
    ഑ஔΛߦ͏͔dry-run͔ɺҰ࿈ͷ഑ஔॲཧΛྻڍͨ͠಺༰(τ
    ϥϯβΫγϣϯ)ͱ͍ͬͨίϯςΩετΛѻ͑Δ

    View Slide

  48. ͬ͘͟Γͱͨ͠ྲྀΕͷΠϝʔδ(requireΛྫʹ)
    ͔ͳΓೖΓ૊ΜͰ͍Δɾɾɾ͚ͲɺཁॴཁॴͰhookͰ͖Δ͜ͱΛײͯ͡΋Β͑Ε͹ͱ

    View Slide

  49. େࣄͳͷ͸ɾɾɾ
    • શͯͷΠϕϯτ΍ྲྀΕΛ֮͑Δඞཁ͸ͳͯ͘
    • ʮΠϕϯτʹ͸छྨ͕͋Δʯͷͱ
    ʮछྨ͝ͱʹ͍࣋ͬͯΔίϯςΩετ৘ใ͕ҧ͏ʯ
    ͱ͍͏ͷ͕େࣄ
    • ۩ମతͳΠϕϯτͷྲྀΕΛ௫Ήʹ͸ɺ
    ࣮ࡍʹ࣮ߦͯ͠ோΊͯΈΔͷ͕खͬऔΓૣͦ͏ˍ෼͔Γ΍ͦ͢͏

    View Slide

  50. ࣮ࡍʹΠϕϯτ͕ൃՐ͞ΕΔ༷ࢠΛ֬ೝ͢Δʹ͸
    ؀ڥม਺΍Composerʹ౉͢ΦϓγϣϯͰɺσόοά৘ใΛදࣔͤ͞
    Δ͜ͱ͕Ͱ͖Δ
    • ؀ڥม਺ `COMPOSER_DEBUG_EVENTS=1`
    • ΠϕϯτൃՐ࣌ʹ৘ใΛදࣔ͢Δ
    • Φϓγϣϯ `-vvv`
    • ॲཧ಺༰ΛσόοάϨϕϧͰදࣔ͢Δ

    View Slide

  51. ࣮ࡍͷྲྀΕͰDPNQPTFSSFRVJSFதʹΠϕϯτ͕ൃՐ͞ΕΔ༷ࢠ
    ˞Θ͔Γ΍͘͢͢ΔͨΊʹɺҰ෦$PNQPTFSͷTSDΛվม࣮ͯ͠ߦ͍ͯ͠·͢

    View Slide

  52. ࣮ࡍͷྲྀΕͰDPNQPTFSSFRVJSFதʹΠϕϯτ͕ൃՐ͞ΕΔ༷ࢠ
    ˞Θ͔Γ΍͘͢͢ΔͨΊʹɺҰ෦$PNQPTFSͷTSDΛվม࣮ͯ͠ߦ͍ͯ͠·͢

    View Slide

  53. ࣮ࡍͷྲྀΕͰDPNQPTFSSFRVJSFதʹΠϕϯτ͕ൃՐ͞ΕΔ༷ࢠ
    ˞Θ͔Γ΍͘͢͢ΔͨΊʹɺҰ෦$PNQPTFSͷTSDΛվม࣮ͯ͠ߦ͍ͯ͠·͢

    View Slide

  54. ࣮ࡍͷྲྀΕͰDPNQPTFSDPNNBOEதʹΠϕϯτ͕ൃՐ͞ΕΔ༷ࢠ UIBOLT

    ˞Θ͔Γ΍͘͢͢ΔͨΊʹɺҰ෦$PNQPTFSͷTSDΛվม࣮ͯ͠ߦ͍ͯ͠·͢

    View Slide

  55. ࣮ࡍͷྲྀΕͰDPNQPTFSDPNNBOEதʹΠϕϯτ͕ൃՐ͞ΕΔ༷ࢠ UIBOLT

    ˞Θ͔Γ΍͘͢͢ΔͨΊʹɺҰ෦$PNQPTFSͷTSDΛվม࣮ͯ͠ߦ͍ͯ͠·͢

    View Slide

  56. これらのタイミングに
    好きな処理を挟み込むことで
    「⾃PJを便利にする」ことが出来る!

    View Slide

  57. Ͳ͏͍͏ॲཧ͕ڬΊΔͷʁ
    • PluginΦϒδΣΫτ͸ɺComposerΦϒδΣΫτͱIOΦϒ
    δΣΫτΛར༻Ͱ͖Δ
    • Composer͕࢖͑Δ = PJ৘ใ΍ύοέʔδ৘ใΛѻ͑Δ
    • IO͕࢖͑Δ = ίϯιʔϧ΍ϑΝΠϧ΁ͷೖग़ྗΛѻ͑Δ
    • EventΦϒδΣΫτɾCommandΦϒδΣΫτͱˢͷ2ͭΛ
    ૊Έ߹Θͤͯɺ೚ҙͷॲཧΛ࣮ݱ͍ͯ͘͠

    View Slide

  58. §3
    すごく簡単なPluginの実装例

    View Slide

  59. ͜ΜͳྫΛ༻ҙ͠·ͨ͠
    { ػೳ }
    ύοέʔδΛΠϯετʔϧ/Ξοϓσʔτͨ͠ࡍʹɺPJ͕௚
    ઀ґଘ͍ͯ͠Δύοέʔδͷ࠷ऴߋ৽೔Λදࣔ͢Δ
    { ར༻ํ๏(ىಈํ๏) }
    1. Πϕϯτʹhookͯ͠ൃՐ
    2. ಠࣗίϚϯυͱͯ͠ར༻

    View Slide

  60. §3-1
    イベントにhookして発⽕する機能

    View Slide

  61. SFRVJSFޙʹಈ͘Α͏ʹɺQPTUVQEBUFDNEʹIPPL͍ͯ͠Δྫ

    View Slide

  62. SFRVJSFޙʹಈ͘Α͏ʹɺQPTUVQEBUFDNEʹIPPL͍ͯ͠Δྫ

    View Slide

  63. ΠϕϯτͰhook͢ΔPluginΛ࡞ΔͨΊͷେ·͔ͳྲྀΕ
    1. composer.jsonΛPlugin༻ʹઃఆ͢Δ
    2. PluginInterfaceΛ࣮૷ͨ͠PluginຊମΛ࡞੒͢Δ
    3. PluginʹEventSubscriberInterfaceΛ࣮૷͢Δ
    4. ࣮ࡍͷॲཧΛߦ͏ϩδοΫΛ࣮૷͢Δ

    View Slide

  64. composer.jsonͷઃఆᶃ
    まずはtypeを `composer-plugin` に

    View Slide

  65. composer.jsonͷઃఆᶄ
    requireに`composer-plguin-api`を⼊れる

    View Slide

  66. composer.jsonͷઃఆᶅ
    extra.classにPlugin本体となるファイルを指定する

    View Slide

  67. શମ૾͜Μͳײ͡
    typeの指定
    classの指定
    composer-plugin-apiの
    require

    View Slide

  68. Pluginͷ࡞੒ᶃ
    PluginInterfaceを使って、3つのメソッドを実装する

    View Slide

  69. Pluginͷ࡞੒ᶃ(ଓ͖)
    余談: 素朴なプラグインで良いなら中⾝はスカスカでもOKそう

    View Slide

  70. EventSubscriberInterfaceͷ࣮૷
    `getSubscribedEvents()`メソッドを実装して、
    { 購読するイベント => 発⽕するメソッド }の連想配列を返します

    View Slide

  71. ͜Μͳײ͡ʹͰ͖͕͋Γʂ

    View Slide

  72. IPPLͷσόοάʹ͸ɺASVOTDSJQU&7&/[email protected]/".&A΋ར༻Մೳ

    View Slide

  73. §3-2
    独⾃コマンドを追加して実⾏させる機能

    View Slide

  74. DPNNBOEΛ࣮ߦ͍ͯ͠Δྫ

    View Slide

  75. ίϚϯυΛఏڙ͢ΔPluginΛ࡞ΔͨΊͷେ·͔ͳྲྀΕ
    1. composer.jsonΛPlugin༻ʹઃఆ͢Δ
    2. PluginInterfaceΛ࣮૷ͨ͠PluginຊମΛ࡞੒͢Δ
    3. PluginʹCapableΛ࣮૷͢Δ
    4. CommandProviderΛ࣮૷͢Δ
    5. ࣮ࡍͷॲཧΛߦ͏CommandΦϒδΣΫτΛ࣮૷͢Δ

    View Slide

  76. Capableͷ࣮૷
    `getCapabilities()`メソッドを実装して、
    { Capability => Capabilityの実装クラス }の連想配列を返します

    View Slide

  77. Capabilityͷ࣮૷
    `getCommands()`メソッドを実装して、
    [ `Symfony\Component\Console\Command` のオブジェクト ]の配列を返します

    View Slide

  78. §3-3
    ロジック部分はどんなことをしているの

    View Slide

  79. એ఻
    Composerͷ಺෦ॲཧతͳ࿩͕ೖͬͯ͘ΔͷͰɺ
    աڈͷൃද΋͝ཡ͍ͩ͘͞ɾɾʂ
    IUUQTTQFBLFSEFDLDPNPIMFUTSFBEDPNQPTFS
    IUUQTTQFBLFSEFDLDPNPIMFUTSFBEDPNQPTFS

    View Slide

  80. શମ૾͜Μͳײ͡
    Plugin΍Command͔Βɺ
    ReleaseDateDumper::process()ʹ
    ॲཧΛؙ౤͍͛ͯ͠·͢

    View Slide

  81. ࣗPJͷґଘύοέʔδΛऔಘ
    • Plugin΍Command͔Βड͚औͬͨ
    ComposerΦϒδΣΫτΛར༻ͯ͠ɺґଘύοέʔδΛऔಘ͢Δ
    • `$composer->getPackage()` ͸ɺࣗPJΛ1ͭͷPackageͱΈͳͯ͠ѻ͍ͬͯΔ
    • =>ʮ(PJͷ)composer.jsonΛᷰͬͨΦϒδΣΫτʯʹͳ͍ͬͯΔΠϝʔδ
    • ͦͷͨΊ `$package->getRequires()` `$package->getDevRequires()` ͱ͢Ε͹ɺґଘύοέʔ
    δͷ৘ใΛऔಘ͢Δ͜ͱ͕Ͱ͖Δ (LinkΦϒδΣΫτ)

    View Slide

  82. ґଘPackageຊମͷ৘ใΛऔಘ
    • ᶃ LinkΦϒδΣΫτ͸ʮύοέʔδ໊ʯʮར༻όʔδϣϯʯͱ͍ͬͨ৘ใؚ͕·Ε͍ͯΔ
    • ᶄ InstalledRepository͸ʮΠϯετʔϧ͞ΕͨPackage܈ʯΛू໿؅ཧ͢ΔϨϙδτϦ
    • ᶄʹରͯ͠ᶃͰಘͨ৘ใΛ౤͛Δ͜ͱͰɺPackagຊମͷ৘ใΛऔಘ͢Δ͜ͱ͕Ͱ͖Δ

    View Slide

  83. Package͔Βؔ৺ͷ͋Δ৘ใΛऔಘ
    • ࠓճͷϓϥάΠϯ͸ʮ࠷ऴϦϦʔεͷ೔෇ʯ͕ཉ͍͠
    • PackageΦϒδΣΫτ͔Βऔಘ͢Δ͜ͱ͕Ͱ͖Δ

    View Slide

  84. ἧ͑ͨσʔλΛ੔ܗͯ͠ग़ྗ
    • IOΠϯλʔϑΣΠε͕౉͖͍ͬͯͯΔͷͰɺͦΕΛհͯ͠Ξ΢τϓοτΛߦ͏
    • ͜ΕͰग़དྷ্͕Γʂʂʂ

    View Slide

  85. ͱ͍͏Θ͚Ͱɺ͜Μͳ෩ʹಈ͘ͷͰͨ͠

    View Slide

  86. §4
    ⾊々なPluginの中⾝を
    雰囲気で読んでみる

    View Slide

  87. ͬ͘͟Γͱͨ͠࢓૊Έʹ৮ΕͨͷͰɺ
    ੈͷதʹଘࡏ͢ΔϓϥάΠϯ͕
    ʮ࣮ࡍͲΜͳײ͡ͳͷʯΛோΊͯΈ·͠ΐ͏

    View Slide

  88. bamarni/composer-bin-plugin
    • ઌఔ΋঺հͨ͠΍ͭͰ͢ʂ
    • ʮnamespace(೚ҙͷσΟϨΫτϦ)ʯΛִ཭ͯ͠ɺ
    ͦ͜Ͱಈ͔ͤΔΑ͏ʹ͢Δɾɾɾɾʂ
    • ͬͯϝονϟෳࡶͳ͜ͱΛ͍ͯ͠Δ༧ײ͕͠·ͤΜ͔ʁ

    View Slide

  89. bamarni/composer-bin-plugin
    CLIͷೖྗ͔ΒnamespaceΛऔಘͯ͠
    ‘all’Ͱͳ͚Ε͹ɺ
    ʮnamespaceͷதͰ࣮ߦʯͷϝιουΛݺͿ
    namespaceʹରԠ͢ΔσΟϨΫτϦʹҠಈͯ͠
    ࣮ߦʂʂʂʂʂʂ

    View Slide

  90. cweagans/composer-patches
    • ComposerͰinstallͨ͠ޙʹɺϑΝΠϧͷ಺༰ʹ೚ҙͷ
    patchΛ౰ͯΔ͜ͱΛՄೳʹ͢ΔϓϥάΠϯ
    • ౤͛ͨPRͷରԠ଴ͪͱ͔ɺόʔδϣϯΞοϓ௥ैΛ଴ͬ
    ͍ͯΔ࣌ͳͲʹ΋ศར

    View Slide

  91. cweagans/composer-patches
    ύοέʔδͷΠϯετʔϧɾΞοϓσʔτʹͿΒԼ͛ͯ
    Installerܦ༝ͰɺPackageͷΠϯετʔϧઌύεΛऔಘ͠
    ϩʔΧϧʹ͋ΔPackageͷ࣮ମͷ৘ใΛऔಘ͠
    composer.jsonͷextraϒϩοΫʹهड़ͨ͠
    patchͷ৘ใΛ൓෮
    patchͷద༻ʂ

    View Slide

  92. Composer, Package, IO, Eventɾɾɾ
    ͦΕͧΕ͕ἧ͍ͬͯͯɺ૊Έ߹Θ͍ͤͯ͘͜ͱͰ
    ૉఢͳΞΠσΟΞ͕࣮ݱͰ͖ͦ͏ͳײ͕͖ͯ͡͠·ͤΜ͔ʂ
    (ͱ͍͏͜ͱΛ͓఻͑͢ΔίʔφʔͰͨ͠)

    View Slide

  93. §X
    まとめ

    View Slide

  94. కΊͷ୅ΘΓʹ
    • ʮͨͩύοέʔδͱόʔδϣϯΛࢦఆͯ͠ɺ഑ஔ͢Δ͚ͩʯͰ͸ͳ͍
    ComposerͷϙςϯγϟϧΛײ͍͚ͯͨͩ͡·͔ͨ͠ʂ
    • ύοέʔδϚωʔδϟͱͯ͠ͷ֦ு΍ɺ
    ͦΕʹཹ·Βͳ͍ʮPHP։ൃऀͷͨΊͷ৭ʑ֦ுʯ΋
    (ΞΠσΟΞ࣍ୈͰ)ແݶେͰ͢Ͷɾɾʂ
    • Ҿ͖ग़͠Λ૿΍͓ͯ͘͠ɺͱ͍͏ҙຯͰ
    ·ͣ͸Կͱͳ͘Composer PluginΛ࡞੒ͯ͠Έͯ͸͍͔͕Ͱ͠ΐ͏͔ʂ

    View Slide

  95. ͓·͚
    • ࠓճͷൃදͷதͰ͸ѻΘͳ͔ͬͨɺࡉ͔͍࿩΍tipsͳͲͷ
    AppendixΛSpeakerDeckΞοϓϩʔυ൛ʹ͸ࡌͤͯ͋Γ·͢
    • PHP Conference 2016ͰߦΘΕͨ@Hiraku͞Μͷൃද
    ʮComposerϓϥάΠϯͷ࡞Γํʯ΋େมࢀߟʹͳΓ·͢ʂ
    • https://www.youtube.com/watch?v=8KjcmosXGKM
    • ࡉ͔͍ࠩ෼͸͋ΕͲɺجຊతͳ෦෼͸ݱࡏ΋ͦͷ··࢖͑Δ
    ͸ͣͰ͢

    View Slide

  96. ご清聴
    ありがとうございました🎉

    View Slide

  97. §XX
    Appendix

    View Slide

  98. §XX-1
    Eventの詳細

    View Slide

  99. ͲΜͳΠϕϯτ͕͋ΔͷͰ͔͢ʁ
    • େ·͔ʹ4ܥ౷ͷΠϕϯτ͕͋Δ
    • Plugin Events / Command Events / Package Events /
    Installer Events
    • Πϕϯτ͸ͦΕͧΕʹԠͨ͡ίϯςΩετ৘ใΛؚ༗ͯ͠
    ͓ΓɺϦεφ͸ͦΕΒͷ৘ใͱCompoerΦϒδΣΫτɾIO
    ΦϒδΣΫτΛ૊Έ߹Θͤͯ೚ҙͷॲཧΛ࣮૷͢Δ
    ࢀߟ
    &WFOUOBNFT
    IUUQTHFUDPNQPTFSPSHEPDBSUJDMFTTDSJQUTNEFWFOUOBNFT
    ࠶ܝ

    View Slide

  100. EventΫϥεͱEvent໊ͷఆٛ
    • `○○Events` ΫϥεʹΠϕϯτ໊ͷҰཡ͕ఆٛ͞Ε͍ͯΔ
    • ex) ` Composer\Script\ScriptEvents::PRE_UPDATE_CMD // ’pre-update-cmd’`
    • `○○Event` Ϋϥε͕छྨʹԠͨ͡ΠϕϯτͷΫϥεʹͳΔ
    • ex) `Composer\Script\Event extends Composer\EventDispatcher\Event`
    • Plugin EventsܥͷEventͷΈಛघͰɺʮEvents - Eventʯͷؔ܎͕1:NʹͳΔ
    • EventΫϥεͷίϯετϥΫλͷҧ͍ʹΑΓɺίϯςΩετʹԠͯ͡Ҿ͖౉͞Ε
    Δ৘ใͷࠩҟ͕ੜ͍ͯ͡Δ

    View Slide

  101. ֤Πϕϯτ܈ͷॴࡏ(○○Events)
    Πϕϯτ໊͸ɺ4ͭͷఆٛΫϥεͰఆٛ(ྻڍ)͞Ε͍ͯΔɻ
    4ܥ౷ͷΠϕϯτ͸ɺͦΕͧΕҟͳΔnamespaceʹଐ͢Δ
    1. Plugin Events => Composer\Plugin\PluginEvents
    2. Command Events => Composer\Script\ScriptEvents
    3. Package Events => Composer\Installer\PackageEvents
    4. Installer Events => Composer\Installer\InstallerEvents
    ࢀߟ
    $PNNBOE&WFOUT
    IUUQTHFUDPNQPTFSPSHEPDBSUJDMFTTDSJQUTNEFWFOUOBNFT

    View Slide

  102. Composer\Plugin
    Composer\EventDispatcher
    ֤Πϕϯτͷؔ܎
    Event
    CommandEvent
    PostFileDownloadEvent
    PreCommandRunEvent
    PrePoolCreateEvent
    PreFileDownloadEvent
    PluginEvents

    View Slide

  103. Composer\Script
    Composer\EventDispatcher
    ֤Πϕϯτͷؔ܎
    Event Event ScriptEvents
    Composer\Installer
    InstallerEvent InstallerEvents
    PackageEvent PackageEvents

    View Slide

  104. • EventDispatcher͕ɺΠϕϯ
    τͷछྨʹԠͯ͡ϥοϓͨ͠
    σΟεύονϝιουΛ࣋ͭ
    • Plugin EventsܥͷΠϕϯτʹ
    ͍ͭͯ͸ɺૉͷ `dispatch()`͕
    ར༻͞ΕΔ
    • EventΦϒδΣΫτͷੜ੒
    ͷ੹೚Λݺͼग़͠ଆʹҕͶ
    Δ
    ؔ࿈: EventDispatcher
    Composer\EventDispatcher\EventDispatcher
    +dispatch($eventName, $event)
    +dispatchScript($eventName, $devMode = false,
    $additionalArgs, $flags)
    +dispatchPackageEvent($eventName, $devMode,
    $localRepo, $operations, $operation)
    +dispatchInstallerEvent($eventName, $devMode,
    $executeOperations, $transaction)

    View Slide

  105. Πϕϯτ໊Ұཡ: Plugin Eventsᶃ
    src: \ Composer\Plugin\PluginEvents
    • init
    ComposerΠϯελϯεͷ࡞੒࣌
    ※Ұ෦ͷCommandΫϥεͰ͸executeϝιου಺ͰComposerΠϯελϯεΛ
    ੜ੒͢Δॲཧ͕ೖΔͨΊɺ1ίϚϯυͷ࣮ߦ࣌ʹ2ճൃՐ͢ΔՄೳੑ͕͋Δ
    • pre-command-run
    ComposerίϚϯυͷ࣮ߦલ(ίϚϯυΦϒδΣΫτͷॳظ
    Խ࣌)

    View Slide

  106. Πϕϯτ໊Ұཡ: Plugin Eventsᶄ
    src: \ Composer\Plugin\PluginEvents
    • command
    ComposerίϚϯυͷ࣮ߦ࣌(ίϚϯυىಈ௚ޙ)
    • pre-file-download /post-file-download
    ϑΝΠϧͷDLલޙ(ύοέʔδ৘ใɺύοέʔδຊମ౳)
    • pre-pool-create
    ґଘؔ܎ղܾͷͨΊͷPoolΦϒδΣΫτ࡞੒લ
    ※ `PluginEvents::command` ͱɺυΩϡϝϯτ্ͰʮCommand Eventsʯͱͯ͠঺հ͞Εͯ
    ͍Δ `ScriptEvents::xxx` / `ScriptEvent`͕ଘࡏ͢Δͷ͕ฆΒΘ͍͠ɾɾɾ

    View Slide

  107. Πϕϯτ໊Ұཡ: Command Eventsᶃ
    src: \Composer\Script\ScriptEvents
    • pre-install-cmd / post-install-cmd
    .lockϑΝΠϧ͕ଘࡏ͢Δࡍͷ `composer install` ͷલޙ
    • pre-update-cmd / post-update-cmd
    `composer update`ɺ΋͘͠͸ .lockϑΝΠϧ͕ଘࡏ͠ͳ͍
    ࡍͷ `composer install` ͷલޙ

    View Slide

  108. Πϕϯτ໊Ұཡ: Command Eventsᶄ
    src: \Composer\Script\ScriptEvents
    • pre-status-cmd / post-status-cmd
    `composer status` ͷલޙ
    • pre-archive-cmd / post-archive-cmd
    `composer archive` ͷલޙ
    • pre-autoload-dump / post-autoload-dump
    `composer install[update]`ͷautoload࡞੒ϑΣʔζ΍`composer
    dumpautoload` ͷલޙ
    • post-root-package-install / post-create-project-cmd
    `composer create-project` ͷલޙ

    View Slide

  109. Πϕϯτ໊Ұཡ: Package Events
    src: \Composer\Installer\PackageEvents
    • pre-package-install / post-package-install
    ύοέʔδͷΠϯετʔϧલޙ
    • pre-package-update / post-package-update
    ύοέʔδͷΞοϓσʔτલޙ
    • pre-package-uninstall / post-package-uninstall
    ύοέʔδͷΞϯΠϯετʔϧલޙ

    View Slide

  110. Πϕϯτ໊Ұཡ: Installer Events
    src: \Composer\Installer\InstallerEvents
    • pre-operations-exec
    install/upgradeॲཧ࣌ͷ.lockϑΝΠϧͷ࡞੒ɾߋ৽ޙʙ
    vendorԼ΁ͷύοέʔδͷ഑ஔͷલ

    View Slide

  111. ิ଍: ͳͥPlugin Events͸ʮPluginʯͳͷ͔ʁ
    • ݩʑ͸ʮΠϯετʔϧ΍ΞοϓσʔτͷલޙͰॲཧΛ͸͞
    Έ͍ͨʯͱ͍͏՝୊Λղܾ͢ΔͨΊʹʮTriggerʯͱ͍͏࢓
    ૊Έ͕͋Γɺͦ͜Ͱ TriggerEventsΛൃՐ͍ͤͯͨ͞
    • ޙʹɺTriggerEventsScriptEventsʹมߋ͞ΕΔ
    ࢀߟྺ্࢙ͷٞ࿦΍εφοϓγϣοτ
    IUUQTHJUIVCDPNDPNQPTFSDPNQPTFSCMPCFFEPDGBRTUSJHHFSTNE
    IUUQTHJUIVCDPNOBEFSNBODPNQPTFSDPNNJUBEE

    View Slide

  112. ิ଍: ͳͥPlugin Events͸ʮPluginʯͳͷ͔ʁ
    • ͦͷޙɺΑΓ൚༻తͳ֦ுػߏΛೖΕΑ͏ͱ͍͏͜ͱͰPluginͷ
    ΞΠσΟΞ͕औΓೖΕΒΕͨ
    • ౰ॳ͸ʮಛघͳϨϙδτϦ͔ΒύοέʔδΛऔಘ͢ΔΧελϜ
    ΠϯετʔϥʔʯͷΑ͏ͳϢʔεέʔεΛ૝ఆ
    • ͦͷࡍʹ༻ҙ͞Εͨͷ͕PluginEvents.php
    • ࠷ॳʹcommand, pre-file-download͕ఆٛ͞Ε͍ͯͨ
    ࢀߟྺ্࢙ͷٞ࿦΍εφοϓγϣοτ
    IUUQTHJUIVCDPNDPNQPTFSDPNQPTFSQVMM
    IUUQTHJUIVCDPNDPNQPTFSDPNQPTFSQVMM

    View Slide

  113. §XX-2
    イベントライフサイクルを追う

    View Slide

  114. ৄ͠໨ʹΠϕϯτͷྲྀΕΛ௥ͬͯΈΔ
    • PHPerKaigiͰͷൃද࣌ʹѻͬͨ୊ࡐΛɺ಺෦ߏ଄ͱরΒ͠߹Θ
    ͤͳ͕Β௥ͬͨ΋ͷΛެ։͍ͯ͠·͢
    • ͨͩ͠ɺ͋͘·Ͱʮ࡞ۀ࣌ʹࣗ෼༻ͷϝϞͱͯ͠࢒ͨ͠΋ͷʯ
    ͘Β͍ͷײ֮ͳͷͰɺਖ਼֬ੑʹ͍ͭͯ͸อূ͠·ͤΜ
    • βοΫϦͱͨ͠ొ৔ਓ෺΍࣌ܥྻͷ੔ཧʹ͓໾ཱ͍ͯͩ͘͞ʂ
    • DLͯ͠ޚཡ͍ͩ͘͞
    DPNQPTFSSFRVJSFͷॲཧΛ௥ͬͯΈΔ GPS1)1FS,BJHJ
    4QFBLFS%FDL
    IUUQTTQFBLFSEFDLDPNPIDPNQPTFSSFRVJSFDPNNBOEFWFOUTTFRVFODF

    View Slide

  115. §XX-3
    Composer Plugin開発時のtips

    View Slide

  116. Plugin։ൃ࣌ʹ஌͓ͬͯ͘ͱ
    1. ϩʔΧϧʹ͋Δύοέʔδͷ௥Ճํ๏ɺ։ൃ४උ
    2. σόοά༻Φϓγϣϯ
    3. Xdebugͷѻ͍ํ

    View Slide

  117. 1. ϩʔΧϧʹ͋Δύοέʔδͷ௥Ճํ๏ɺ։ൃ४උ
    • Composer͸ɺϩʔΧϧγεςϜ্ͷύοέʔδΛࢦఆͯ͠ར༻
    ͢Δ͜ͱ͕ग़དྷΔ
    • ཧ۶ͱͯ͠͸ʮRepositoryʯͱͯ͠ʮ(ϩʔΧϧͷ)σΟϨΫτϦ
    Λ௥Ճʯ͠ɺComposer͕ґଘύοέʔδΛղܾ͢Δࡍͷݕࡧ
    ઌͱͯ͠ѻ͑ΔΑ͏ʹ͢Δͱ͍͏΋ͷ
    • comopser.jsonʹඞཁͳઃఆΛՃ͑Δ
    υΩϡϝϯτ3FQPTJUPSJFTQBUI
    IUUQTHFUDPNQPTFSPSHEPDSFQPTJUPSJFTNEQBUI

    View Slide

  118. repositoriesʹɺtypeͱurlΛࢦఆͯ͠
    require, require-devʹύοέʔδ໊Λࢦఆ͢Δ
    γϯϘϦοΫϦϯΫ͕షΒΕ͍ͯΔ༷ࢠ

    View Slide

  119. 1. ϩʔΧϧʹ͋Δύοέʔδͷ௥Ճํ๏ɺ։ൃ४උ
    • Composer಺෦ͷڍಈΛ(ॻ͖׵͑ͳ͕Β)ಈ͔͍ͨ͠ͱ͖
    ͸ɺιʔείʔυΛམͱ͓͍࣮ͯͯ͠ߦ͢Δͱ˕
    • ཁ͢Δʹɺ require͓͍ͯͯ͠vendor/binͷ΋ͷΛ࢖͏

    View Slide

  120. 2. σόοά༻Φϓγϣϯ
    • ֤ίϚϯυڞ௨ͷΦϓγϣϯͱͯ͠ `-vvv` ͕͋Γɺσόοά৘ใͷ
    ग़ྗΛߦ͑Δ
    • ؀ڥม਺ `COMPOSER_DEBUG_EVENTS=1` ʹ͢ΔͱɺΠϕϯτͷ
    ൃՐ৘ใͷग़ྗΛߦ͑Δ
    • ͦͷଞʹ΋ɺHOME΍CACHEͷσΟϨΫτϦͷมߋ΍ɺωοτ
    ϫʔΫͷແޮԽͱݴͬͨ։ൃ࣌΍σόοάʹศརͳ߲໨΋
    ࢀߟ
    $-*(MPCBM0QUJPOTcIUUQTHFUDPNQPTFSPSHEPDDMJNEHMPCBMPQUJPOT
    $-*&OWJSPONFOU7BSJBCMFTcIUUQTHFUDPNQPTFSPSHEPDDMJNEFOWJSPONFOUWBSJBCMFT

    View Slide

  121. 3. Xdebugͷѻ͍ํ
    • Composer͸௨ৗ࣌ͷڍಈͱͯ͠XdebugΛແޮʹͯ͠ಈ࡞͢Δ
    • εςοϓ࣮ߦ౳ͷར༻ͷͨΊʹXdebugΛར༻͍ͨ͠৔߹ʹ
    ࠔΔ
    • ར༻͢Δʹ͸ɺ؀ڥม਺ `COMPOSER_ALLOW_XDEBUG=1`Λ
    ར༻͢Δ
    ࢀߟ
    DPNQPTFSYEFCVHIBOEMFS
    IUUQTHJUIVCDPNDPNQPTFSYEFCVHIBOEMFS

    View Slide

  122. §XX-4
    allow-plugin-list

    View Slide

  123. allow-plugin-listͬͯͳΜͩΖ͏ʁ
    • ༗ޮʹ͢ΔϓϥάΠϯΛɺcomposer.json্Ͱallow-listܗࣜͰ
    ࢦఆ͢Δඞཁ͕͋Δ
    • 2.2͔Βೖͬͨػೳ
    • ࣮ʹ֮͑ͷͳ͍εΫϦϓτͷ࣮ߦΛ཈੍͢Δ
    • ͜͜ʹແ͍΋ͷ͸ɺϓϥάΠϯͷಡΈࠐΈ࣌ʹεΩοϓ͞ΕΔ
    ࢀߟ
    $PNQPTFS3FMFBTF
    IUUQTCMPHQBDLBHJTUDPNDPNQPTFS

    View Slide

  124. 参考: 実際の処理部分
    src: https://github.com/composer/composer/blob/2.2/src/Composer/Plugin/PluginManager.php#L398-L401

    View Slide

  125. おしまい!
    今回利⽤したソースコード等は、
    https://github.com/o0h/phperkaigi-2022-zairyo
    にアップロードします(予定)

    View Slide