$30 off During Our Annual Pro Sale. View Details »

#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_ [഑෍൛]
  2. PHPer͸ComposerʹٹΘΕ·ͨ͠ ͋Γ͕ͱ͏໊લۭؒɺ͋Γ͕ͱ͏Φʔτϩʔυ • 2006೥ / PHP5.1.2: spl_autoload_registerͷࢥ͍ग़ • 2009೥ /

    PHP5.3.0: ॳΊͯͷ໊લۭؒͷࢥ͍ग़ • 2009೥: PHP Standards GroupͱPSR-0ͷࢥ͍ग़ • 2010೥: SplClassLoader(RFC)ͷࢥ͍ग़
  3. PHPer͸ComposerʹٹΘΕ·ͨ͠ • 2011೥: Composer/Packagist։ൃ։࢝ • 2012೥3݄: Composer 1.0.0-alpha1 2012೥3݄

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

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

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

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

  8. ࣗݾ঺հ • ⾦城秀樹 / きんじょうひでき • GitHub: @o0h / Twitter:

    @o0h_ • 好きなFWはCakePHP • アイコンは 美味しい鮭親⼦丼の写真です
  9. §0 イントロ

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

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

    •͢ͳΘͪϓϩδΣΫτͷ ʮఆٛʯʮ૊ΈཱͯʯΛ ୲͍ͬͯΔ
  12. As ґଘ(ύοέʔδ)ͷ؅ཧπʔϧ • ඞཁͳύοέʔδͷ औಘɾ഑ஔɺߋ৽Λߦ ͏ػೳΛఏڙ • ద੾ͳऔಘઌͷ൑அ ΍֤ݸͷύοέʔδͷ ཁٻΛղܾ͢Δ

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

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

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

  16. ͓͠ͳ͕͖ 1.ຊ౰ʹ͋ͬͨʂComposer Plugin ʙ࣮ྫἫʙ 2. ֓આ: Composer Plugin 3. ͘͢͝؆୯ͳPluginͷ࣮૷ྫ

    4. ৭ʑͳPluginͷத਎ΛงғؾͰಡΜͰΈΔ 時間に余裕があれば!
  17. §1 本当にあった! Composer Plugin 〜実例篇〜

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

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

  20. composer require symfony/thanks { ֦ுϙΠϯτ: ಠࣗͷίϚϯυΛ௥Ճ͢Δ } • `composer thanks`ͱ͍͏ίϚϯυΛ௥Ճ

    • ͋ͳͨͷϓϩδΣΫτͰ͓ੈ࿩ʹͳ͍ͬͯΔύοέʔδʹ GitHubͷελʔΛૹͬͯ͘ΕΔʂ
  21. UIBOLTͱ͍͏ಠࣗίϚϯυ͕௥Ճ͞Εɺ ࣮ߦ͢Δͱ(JU)VCϨϙδτϦʹ˒Λ෇͚Δ

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

  23. composer require phpstan/extension-installer { 拡張ポイント: パッケージの追加時の挙動を追加する } • PHPStanのextensionがrequire/update時に、 ⾃動的にプラグインを有効化

    • PHPStanが読み込みに⾏くように設定ファイルに追記 • 設定ファイルを⼿動でいじる必要がなくなる!
  24. UZQFQIQTUBOFYUFOTJPOͳύοέʔδͷಋೖʹ൓Ԡͯ͠ɺ ઃఆϑΝΠϧͷߋ৽Λߦ͏

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

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

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

  28. composer require bamarni/composer-bin-plugin { ֦ுϙΠϯτ: Πϯετʔϧͷઓུ(ϑΝΠϧͷ഑ஔઌ)Λมߋ͢Δ } • ։ൃܥͷπʔϧ(౳)Λɺ௨ৗͷvendorͱ͸ผͷ৔ॴʹ഑ஔ͢Δ •

    ؒ઀తʹґଘ͢Δύοέʔδ౳ͷίϯϑϦΫτΛղফ͢Δ • ʮϓϩμΫτίʔυͱlinterπʔϧͰཁٻ͢Δόʔδϣϯ͕ҧ ͏ʂʯͱ͍ͬͨ࣌ʹ΋ɺʮͦΕͧΕ͕ඞཁͳґଘόʔδϣϯΛ ֬อ͢Δʯ͜ͱ͕Ͱ͖Δ
  29. 1IBO 1IQ.FUSJDTΛִ཭ͯ͠Πϯετʔϧ

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

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

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

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

  34. §2 概説: Composer Plugin

  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ロジックを⼿に⼊れろ!
  36. Ͳ͏࣮ݱͯ͠ɺԿ͕Ͱ͖ΔͷͰ͔͢ʁ ओʹ2ͭͷhook͕͋Γɺͦ͜ʹҾֻ͚ͬͯಠࣗॲཧΛೖΕࠐΉ 1. ಠࣗCommandΛొ࿥͠ɺར༻͢Δॲཧ 2. Composer͕ൃߦ͍ͯ͠ΔΠϕϯτͷߪಡʹΑΔॲཧ ͦΕͧΕͷํ๏΍λΠϛϯάͰɺ ComposerͷίϯςΩετΛར༻ͨ͠ॲཧΛڬΉ͜ͱ͕Ͱ͖Δ

  37. ಠࣗίϚϯυͷొ࿥ { Capability } Plugin͔ΒɺComposerʹରͯ͠ ʮར༻ՄೳͳίϚϯυҰཡͷऔಘํ ๏ʯΛڞ༗͢Δɻ `Capable::getCapabilities(): array<class-string, class-string>`

    ͷ࣮૷ ྫ: bamarni/composer-bin-plugin ࢀߟ 4FUUJOHVQBOEVTJOHQMVHJOT$PNQPTFS IUUQTHFUDPNQPTFSPSHEPDBSUJDMFTQMVHJOTNEQMVHJO DBQBCJMJUJFT
  38. Plugin Composer プラグイン本体 <Interface> Capable プラグインを 読み込むよ! お、Capability持ってるな 独⾃のコマンドを 提供できます!

    詳しくは プロバイダを参照! <Interface> CommandProvider プロバイダ どんなコマンド ある? コマンドの ⼀覧です! <Interface> PluginInterface コマンド Command DO COMMAND! I DO!
  39. ऄ଍: Command? ComposerͷCommand͸ symfony/consoleΛར༻͍ͯ͠·͢ɻ աڈʹComposerͷ಺෦ߏ଄ʹ͍ͭ ͯͷൃදΛ͓ͯ͠Γ·͢ͷͰɺ͝ڵ ຯ͋Γ·ͨ͠Βޚཡ͍ͩ͘͞ ࢀߟ $PNQPTFSͬͯԿʁͲ͏ಈ͘ͷʁಡΜͰΈ·ͨ͠ʂ IUUQTTQFBLFSEFDLDPNPIMFUTSFBEDPNQPTFS

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

    string|array>` ͷ࣮૷ ྫ: phpstan/extension-installer
  41. Plugin Composer プラグイン本体 <Interface> EventSubscriberInterface プラグインを 読み込むよ! お、Subscriberだな <Interface> PluginInterface

    何を購読してる? 購読の⼀覧です! 処理 イベント発⽕ それ購読してる! I DO SOMETHING!
  42. コマンドの 前処理に⼊るよ! その前に◦◦が使えるか チェックして! イベント プラグイン パッケージの meta情報をDLしたよ! ライセンスを 確認して!

    パッケージの インストールを 完了したよ! tests以下は削除して! レポジトリ情報を 取得するよ! VPN有効? サーバー接続確認して! ྫ: Πϕϯτ㲗ϓϥάΠϯͰ৭ʑͳֻ͚߹͍͕Ͱ͖Δͷਤ .lockファイルを 書き込んだよ! minifyして!
  43. ͲΜͳΠϕϯτ͕͋ΔͷͰ͔͢ʁ • େ·͔ʹ4ܥ౷ͷΠϕϯτ͕͋Δ • Plugin Events / Command Events /

    Package Events / Installer Events • Πϕϯτ͸ͦΕͧΕʹԠͨ͡ίϯςΩετ৘ใΛؚ༗ͯ͠ ͓ΓɺϦεφ͸ͦΕΒͷ৘ใͱCompoerΦϒδΣΫτɾIO ΦϒδΣΫτΛ૊Έ߹Θͤͯ೚ҙͷॲཧΛ࣮૷͢Δ ࢀߟ &WFOUOBNFT IUUQTHFUDPNQPTFSPSHEPDBSUJDMFTTDSJQUTNEFWFOUOBNFT
  44. 1. Plugin Events ComposerͷجװΛ୲͏ॲཧͱͰ΋ݴ͏΂͖λΠϛϯάʹൃՐ͞ΕΔ { ओͳΠϕϯτ } ComposerΦϒδΣΫτͷॳظԽɺCommandͷॳظԽɺϑΝΠϧͷDLલޙͳͲ { ओͳίϯςΩετ

    } ʮϑΝΠϧͷμ΢ϯϩʔυલʯͰ͋Ε͹ʮऔಘઌͷURL৘ใʯɺʮCommandͷ ࣮ߦલ(ॳظԽத)ʯͰ͋Ε͹ʮೖྗ৘ใʯͱ͍ͬͨίϯςΩετΛѻ͑Δ ※ ϓϥάΠϯ಺෦΍ؔ࿈ॲཧʹ͍ͭͯͷΠϕϯτͱ͍͏ࣄͰ͸ͳ͘ɺ ʮϓϥάΠϯͱ͍͏ར༻ऀͷͨΊʹ༻ҙ͞ΕͨΠϕϯτͱ͍͏ػߏͷ͏ͪɺҰൠతͳ΋ͷʯΈ͍ͨͳχϡΞϯεͳͷͩ ͱࢥ͍·͢
  45. 2. Command Events Composerͷ࣋ͭ(ඪ४)ίϚϯυͷ࣮ߦલޙʹൃՐ͞ΕΔ { ओͳΠϕϯτ } ʮinstallʯʮupdateʯʮdumpautoloadʯʮcreate-projectʯͳͲͷ ComposerίϚϯυͷ࣮ߦલɾ࣮ߦޙ {

    ओͳίϯςΩετ } ʮίϚϯυ໊ʯʮinput/outputʯʮ࣮ߦ࣌ύϥϝʔλͱ͍ͬͨίϯ ςΩετΛѻ͑Δ
  46. 3. Package Events ύοέʔδݸผͷల։΍഑ஔɺআڈͷલޙʹൃՐ͞ΕΔ { ओͳΠϕϯτ } ֤ύοέʔδʹର͢Δʮinstallʯʮupdateʯʮremoveʯͷ࣮ߦલɺ ࣮ߦޙ {

    ओͳίϯςΩετ } ର৅ύοέʔδ৘ใ(໊લɾόʔδϣϯetc)ɺૢ࡞಺༰(৽͘͠ஔ͘ͷ ͔ɺߋ৽͢Δͷ͔ɺআڈ͢Δͷ͔)ͱ͍ͬͨίϯςΩετΛѻ͑Δ ※ల։ = ΞʔΧΠϒͷղౚɺ഑ஔ = vendorσΟϨΫτϦԼ΁ͷҠಈ
  47. 4. Installer Events ύοέʔδશମͷ഑ஔ࣮ߦલʹൃՐ͞ΕΔ { ओͳΠϕϯτ } ಛఆ͞Εͨύοέʔδͷऔಘ΍഑ஔͷલ { ओͳίϯςΩετ

    } ഑ஔΛߦ͏͔dry-run͔ɺҰ࿈ͷ഑ஔॲཧΛྻڍͨ͠಺༰(τ ϥϯβΫγϣϯ)ͱ͍ͬͨίϯςΩετΛѻ͑Δ
  48. ͬ͘͟Γͱͨ͠ྲྀΕͷΠϝʔδ(requireΛྫʹ) ͔ͳΓೖΓ૊ΜͰ͍Δɾɾɾ͚ͲɺཁॴཁॴͰhookͰ͖Δ͜ͱΛײͯ͡΋Β͑Ε͹ͱ

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

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

    `-vvv` • ॲཧ಺༰ΛσόοάϨϕϧͰදࣔ͢Δ
  51. ࣮ࡍͷྲྀΕͰDPNQPTFSSFRVJSFதʹΠϕϯτ͕ൃՐ͞ΕΔ༷ࢠ ˞Θ͔Γ΍͘͢͢ΔͨΊʹɺҰ෦$PNQPTFSͷTSDΛվม࣮ͯ͠ߦ͍ͯ͠·͢

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

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

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

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

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

  57. Ͳ͏͍͏ॲཧ͕ڬΊΔͷʁ • PluginΦϒδΣΫτ͸ɺComposerΦϒδΣΫτͱIOΦϒ δΣΫτΛར༻Ͱ͖Δ • Composer͕࢖͑Δ = PJ৘ใ΍ύοέʔδ৘ใΛѻ͑Δ • IO͕࢖͑Δ

    = ίϯιʔϧ΍ϑΝΠϧ΁ͷೖग़ྗΛѻ͑Δ • EventΦϒδΣΫτɾCommandΦϒδΣΫτͱˢͷ2ͭΛ ૊Έ߹Θͤͯɺ೚ҙͷॲཧΛ࣮ݱ͍ͯ͘͠
  58. §3 すごく簡単なPluginの実装例

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

    Πϕϯτʹhookͯ͠ൃՐ 2. ಠࣗίϚϯυͱͯ͠ར༻
  60. §3-1 イベントにhookして発⽕する機能

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

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

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

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

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

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

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

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

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

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

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

  72. IPPLͷσόοάʹ͸ɺASVOTDSJQU&7&/5@/".&A΋ར༻Մೳ

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

  74. DPNNBOEΛ࣮ߦ͍ͯ͠Δྫ

  75. ίϚϯυΛఏڙ͢ΔPluginΛ࡞ΔͨΊͷେ·͔ͳྲྀΕ 1. composer.jsonΛPlugin༻ʹઃఆ͢Δ 2. PluginInterfaceΛ࣮૷ͨ͠PluginຊମΛ࡞੒͢Δ 3. PluginʹCapableΛ࣮૷͢Δ 4. CommandProviderΛ࣮૷͢Δ 5.

    ࣮ࡍͷॲཧΛߦ͏CommandΦϒδΣΫτΛ࣮૷͢Δ
  76. Capableͷ࣮૷ `getCapabilities()`メソッドを実装して、 { Capability => Capabilityの実装クラス }の連想配列を返します

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  93. §X まとめ

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

    ·ͣ͸Կͱͳ͘Composer PluginΛ࡞੒ͯ͠Έͯ͸͍͔͕Ͱ͠ΐ͏͔ʂ
  95. ͓·͚ • ࠓճͷൃදͷதͰ͸ѻΘͳ͔ͬͨɺࡉ͔͍࿩΍tipsͳͲͷ AppendixΛSpeakerDeckΞοϓϩʔυ൛ʹ͸ࡌͤͯ͋Γ·͢ • PHP Conference 2016ͰߦΘΕͨ@Hiraku͞Μͷൃද ʮComposerϓϥάΠϯͷ࡞Γํʯ΋େมࢀߟʹͳΓ·͢ʂ •

    https://www.youtube.com/watch?v=8KjcmosXGKM • ࡉ͔͍ࠩ෼͸͋ΕͲɺجຊతͳ෦෼͸ݱࡏ΋ͦͷ··࢖͑Δ ͸ͣͰ͢
  96. ご清聴 ありがとうございました🎉

  97. §XX Appendix

  98. §XX-1 Eventの詳細

  99. ͲΜͳΠϕϯτ͕͋ΔͷͰ͔͢ʁ • େ·͔ʹ4ܥ౷ͷΠϕϯτ͕͋Δ • Plugin Events / Command Events /

    Package Events / Installer Events • Πϕϯτ͸ͦΕͧΕʹԠͨ͡ίϯςΩετ৘ใΛؚ༗ͯ͠ ͓ΓɺϦεφ͸ͦΕΒͷ৘ใͱCompoerΦϒδΣΫτɾIO ΦϒδΣΫτΛ૊Έ߹Θͤͯ೚ҙͷॲཧΛ࣮૷͢Δ ࢀߟ &WFOUOBNFT IUUQTHFUDPNQPTFSPSHEPDBSUJDMFTTDSJQUTNEFWFOUOBNFT ࠶ܝ
  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ΫϥεͷίϯετϥΫλͷҧ͍ʹΑΓɺίϯςΩετʹԠͯ͡Ҿ͖౉͞Ε Δ৘ใͷࠩҟ͕ੜ͍ͯ͡Δ
  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
  102. Composer\Plugin Composer\EventDispatcher ֤Πϕϯτͷؔ܎ Event CommandEvent PostFileDownloadEvent PreCommandRunEvent PrePoolCreateEvent PreFileDownloadEvent PluginEvents

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

    PackageEvents
  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)
  105. Πϕϯτ໊Ұཡ: Plugin Eventsᶃ src: \ Composer\Plugin\PluginEvents • init ComposerΠϯελϯεͷ࡞੒࣌ ※Ұ෦ͷCommandΫϥεͰ͸executeϝιου಺ͰComposerΠϯελϯεΛ

    ੜ੒͢Δॲཧ͕ೖΔͨΊɺ1ίϚϯυͷ࣮ߦ࣌ʹ2ճൃՐ͢ΔՄೳੑ͕͋Δ • pre-command-run ComposerίϚϯυͷ࣮ߦલ(ίϚϯυΦϒδΣΫτͷॳظ Խ࣌)
  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`͕ଘࡏ͢Δͷ͕ฆΒΘ͍͠ɾɾɾ
  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` ͷલޙ
  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` ͷલޙ
  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 ύοέʔδͷΞϯΠϯετʔϧલޙ
  110. Πϕϯτ໊Ұཡ: Installer Events src: \Composer\Installer\InstallerEvents • pre-operations-exec install/upgradeॲཧ࣌ͷ.lockϑΝΠϧͷ࡞੒ɾߋ৽ޙʙ vendorԼ΁ͷύοέʔδͷ഑ஔͷલ

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

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

    ͦͷࡍʹ༻ҙ͞Εͨͷ͕PluginEvents.php • ࠷ॳʹcommand, pre-file-download͕ఆٛ͞Ε͍ͯͨ ࢀߟྺ্࢙ͷٞ࿦΍εφοϓγϣοτ IUUQTHJUIVCDPNDPNQPTFSDPNQPTFSQVMM IUUQTHJUIVCDPNDPNQPTFSDPNQPTFSQVMM
  113. §XX-2 イベントライフサイクルを追う

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

    DLͯ͠ޚཡ͍ͩ͘͞ DPNQPTFSSFRVJSFͷॲཧΛ௥ͬͯΈΔ GPS1)1FS,BJHJ 4QFBLFS%FDL IUUQTTQFBLFSEFDLDPNPIDPNQPTFSSFRVJSFDPNNBOEFWFOUTTFRVFODF
  115. §XX-3 Composer Plugin開発時のtips

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

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

    comopser.jsonʹඞཁͳઃఆΛՃ͑Δ υΩϡϝϯτ3FQPTJUPSJFTQBUI IUUQTHFUDPNQPTFSPSHEPDSFQPTJUPSJFTNEQBUI
  118. repositoriesʹɺtypeͱurlΛࢦఆͯ͠ require, require-devʹύοέʔδ໊Λࢦఆ͢Δ γϯϘϦοΫϦϯΫ͕షΒΕ͍ͯΔ༷ࢠ

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

  120. 2. σόοά༻Φϓγϣϯ • ֤ίϚϯυڞ௨ͷΦϓγϣϯͱͯ͠ `-vvv` ͕͋Γɺσόοά৘ใͷ ग़ྗΛߦ͑Δ • ؀ڥม਺ `COMPOSER_DEBUG_EVENTS=1`

    ʹ͢ΔͱɺΠϕϯτͷ ൃՐ৘ใͷग़ྗΛߦ͑Δ • ͦͷଞʹ΋ɺHOME΍CACHEͷσΟϨΫτϦͷมߋ΍ɺωοτ ϫʔΫͷແޮԽͱݴͬͨ։ൃ࣌΍σόοάʹศརͳ߲໨΋ ࢀߟ  $-*(MPCBM0QUJPOTcIUUQTHFUDPNQPTFSPSHEPDDMJNEHMPCBMPQUJPOT  $-*&OWJSPONFOU7BSJBCMFTcIUUQTHFUDPNQPTFSPSHEPDDMJNEFOWJSPONFOUWBSJBCMFT
  121. 3. Xdebugͷѻ͍ํ • Composer͸௨ৗ࣌ͷڍಈͱͯ͠XdebugΛແޮʹͯ͠ಈ࡞͢Δ • εςοϓ࣮ߦ౳ͷར༻ͷͨΊʹXdebugΛར༻͍ͨ͠৔߹ʹ ࠔΔ • ར༻͢Δʹ͸ɺ؀ڥม਺ `COMPOSER_ALLOW_XDEBUG=1`Λ

    ར༻͢Δ ࢀߟ DPNQPTFSYEFCVHIBOEMFS IUUQTHJUIVCDPNDPNQPTFSYEFCVHIBOEMFS
  122. §XX-4 allow-plugin-list

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

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

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