Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

§0 イントロ

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

࣮ࡍʹు͖ग़͞ΕΔྫ

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

§2 概説: Composer Plugin

Slide 35

Slide 35 text

݁ہͳΜͳͷͰ͔͢ʁ 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ロジックを⼿に⼊れろ!

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

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

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

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

Slide 73

Slide 73 text

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

Slide 74

Slide 74 text

DPNNBOEΛ࣮ߦ͍ͯ͠Δྫ

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

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

Slide 77

Slide 77 text

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

Slide 78

Slide 78 text

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

Slide 79

Slide 79 text

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

Slide 80

Slide 80 text

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

Slide 81

Slide 81 text

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

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

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

Slide 84

Slide 84 text

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

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

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

Slide 87

Slide 87 text

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

Slide 88

Slide 88 text

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

Slide 89

Slide 89 text

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

Slide 90

Slide 90 text

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

Slide 91

Slide 91 text

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

Slide 92

Slide 92 text

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

Slide 93

Slide 93 text

§X まとめ

Slide 94

Slide 94 text

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

Slide 95

Slide 95 text

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

Slide 96

Slide 96 text

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

Slide 97

Slide 97 text

§XX Appendix

Slide 98

Slide 98 text

§XX-1 Eventの詳細

Slide 99

Slide 99 text

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

Slide 100

Slide 100 text

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ΫϥεͷίϯετϥΫλͷҧ͍ʹΑΓɺίϯςΩετʹԠͯ͡Ҿ͖౉͞Ε Δ৘ใͷࠩҟ͕ੜ͍ͯ͡Δ

Slide 101

Slide 101 text

֤Πϕϯτ܈ͷॴࡏ(○○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

Slide 102

Slide 102 text

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

Slide 103

Slide 103 text

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

Slide 104

Slide 104 text

• 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)

Slide 105

Slide 105 text

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

Slide 106

Slide 106 text

Πϕϯτ໊Ұཡ: 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`͕ଘࡏ͢Δͷ͕ฆΒΘ͍͠ɾɾɾ

Slide 107

Slide 107 text

Πϕϯτ໊Ұཡ: 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` ͷલޙ

Slide 108

Slide 108 text

Πϕϯτ໊Ұཡ: 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` ͷલޙ

Slide 109

Slide 109 text

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

Slide 110

Slide 110 text

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

Slide 111

Slide 111 text

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

Slide 112

Slide 112 text

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

Slide 113

Slide 113 text

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

Slide 114

Slide 114 text

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

Slide 115

Slide 115 text

§XX-3 Composer Plugin開発時のtips

Slide 116

Slide 116 text

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

Slide 117

Slide 117 text

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

Slide 118

Slide 118 text

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

Slide 119

Slide 119 text

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

Slide 120

Slide 120 text

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

Slide 121

Slide 121 text

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

Slide 122

Slide 122 text

§XX-4 allow-plugin-list

Slide 123

Slide 123 text

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

Slide 124

Slide 124 text

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

Slide 125

Slide 125 text

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