🎁

Composerパッケージを作って公開までの手順

2024/12/04に公開

この記事は カオナビ Advent Calendar 2024 4日目の記事です。

はじめに

普段から利用しているComposerパッケージですが、今回は自分でComposerパッケージを作って公開までやってみたいと思います。

環境

  • PHP 8.4.1
  • Composer 2.8.3

事前準備

GitHubのアカウントとPackagistのアカウントは作成しておいてください。

作成から登録までの手順

今回はHello Worldを返すプログラムを作って、それをComposerパッケージとして公開します。

GitHubにリポジトリを作成する

まずはGitHubリポジトリの作成です。

  • Repository nameは公開するパッケージの名前と合わせたい場合は同じにしておくといいかと思います
    この後にも書きますが、パッケージの名前はcomposer.jsonに書いた名前になりますんで、Repositoryの名前と違っても大丈夫です
    今回はGitHubの候補に出ていたautomatic-umbrellaにしました(折り畳み傘です☂️)
  • Descriptionは任意ですが、公開するパッケージの説明を書くのが良いですね
  • Add a README fileにチェックを入れて、README.mdは最初から作っておきます
  • Add .gitignoreはComposerを選んでおきます。Composerを選んでおけば、vendorディレクトリなどが書かれた状態で.gitignoreが作られます
  • Choose a licenseは任意ですが、パッケージを公開するとソースコードも公開することになるので、今回はMITライセンスを選択しておきます

Create repositoryを押してリポジトリの作成は完了です。

https://github.com/naopusyu/automatic-umbrella

Hello Worldを返すプログラムを作成する

さきほど作ったリポジトリをgit cloneで作業するパソコンに複製します。

git clone git@github.com:naopusyu/automatic-umbrella.git

automatic-umbrellaディレクトリができていると思うので、その中にPHPファイルを1つ追加します

touch app/HelloWorld.php

今回は2024年11月21日にリリースされたPHP8.4を使うので、新機能のプロパティフックを利用してHello Worldを返すプログラムを作成します。

app/HelloWorld.php
<?php

declare(strict_types=1);

namespace App;

use Exception;

class HelloWorld
{
    public string $say {
        set => throw new Exception('値の代入はできない');
        get => 'Hello World';
    }
}

composer.jsonファイルを作成する

つぎにcomposer.jsonファイルを作成します。
composer.jsonは手動で作ることもできますし、composer initコマンドを使って対話式で作成することもできます。

どちらを選んでも良いですが。最終的に次のような内容になっていれば大丈夫です。

composer.json
{
    "name": "naopusyu/hello-world",
    "description": "This is a sample Composer package.",
    "type": "library",
    "license": "MIT",
    "authors": [
        {
            "name": "naopusyu"
        }
    ],
    "require": {
        "php": "^8.4.1"
    },
    "autoload": {
        "psr-4": {
            "App\\": "app/"
        }
    }
}
  • nameはComposerパッケージの名前になります。リポジトリの名前と同じでもいいですし、別の名前をつけても大丈夫です。今回は別の名前にしておきます
  • descriptionはComposerパッケージの説明文です。今回はおためしになるので、それらしい文にしてあります
  • typeはデフォルトはlibraryになるので明示的に指定しないでも大丈夫です。今回は説明のために書いておきます
  • licenseはGitHubリポジトリを作成した時に指定したライセンスと同じものを指定しておきます
  • authorsは作成者です。nameやemail、homepageなどを指定できます。今回はわたしのアカウント名を指定しておきます
  • requireは依存するパッケージを指定します
    今回は依存するパッケージはないけど、書いたPHPプログラムがPHP8.4以上でないと動かないのでPHPのバージョンを指定しておきます
  • autoloadはオートローディングの指定です。Composerパッケージ内の存在するクラスの自動読み込みを行うために必要です
    今回はappディレクトリ配下にプログラムを作成したので、上記のような指定になっています

ユニットテストを作成する

今回程度の内容であれば、ユニットテストを作成しないでもいいかもしれないですが、せっかくなので作成します。

ユニットテストにはPHPUnitを使うのでまずはインストールです。

composer require phpunit/phpunit --dev

インストール後、ユニットテストを配置するディレクトリの作成とcomposer.jsonにオートローディングの設定を追記します。

mkdir tests
composer.json
    "autoload": {
        "psr-4": {
            "App\\": "app/"
        }
-   }
+   },
+   "autoload-dev": {
+       "psr-4": {
+           "Tests\\": "tests/"
+       }
+   }
}

ここで追加したautoload-devの設定を反映したいので、composer dump-autoloadコマンドを実行しておきます。

つぎにtestsディレクトリ配下にユニットテストを作成します。

tests/HelloWorldTest.php
<?php

declare(strict_types=1);

namespace Tests;

use App\HelloWorld;
use Exception;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;

class HelloWorldTest extends TestCase
{
    #[Test]
    public function say(): void
    {
        $expected = new HelloWorld();
        $this->assertSame($expected->say, 'Hello World'); 
    }

    #[Test]
    public function exception(): void
    {
        $this->expectException(Exception::class);
        $this->expectExceptionMessage('値の代入はできない');

        $expected = new HelloWorld();
        $expected->say = 'Hell0'; 
    }
}

作成したら動かしておきます。

automatic-umbrella % ./vendor/bin/phpunit tests/HelloWorldTest.php
PHPUnit 11.4.3 by Sebastian Bergmann and contributors.

Runtime:       PHP 8.4.1

..                                                                  2 / 2 (100%)

Time: 00:00.002, Memory: 8.00 MB

OK (2 tests, 3 assertions)

動きましたね🎉

GitHubに公開する

諸々作成が終わりましたので、これまで作成した内容GitHubのリポジトリにpushすることが可能になりましたが、
その前に、.gitignoreファイルの内容を一度整理します。

リポジトリを作成する時に.gitignoreも一緒に作成していますが、内容に不足していない再度確認です。

次にような内容になっていれば、最低限除外できているかと思います。

.gitignore
/vendor/
composer.lock
.DS_Store

確認後、リポジトリにpushしてください。

Composerパッケージとして公開するにはリリースバージョンも必要になってきます。

リリースバージョンの作成はGitHubからでもできますが、git tagコマンドを使っても大丈夫です。

git tag 1.0.0

タグをpushする時は、下記を実行します。

git push origin --tag

これでComposerパッケージが完成です。

Packagistに登録する

つぎに完成したComposerパッケージをPackagistに登録します。

事前に作成しておいたアカウントでログインを行い、画面上部にあるSubmitの画面にいきます。

URLに公開するComposerパッケージのリポジトリを入力して、Checkボタンを押します。
リポジトリに問題がなければ、最後にSubmitを押せば、登録完了です。

https://packagist.org/packages/naopusyu/hello-world

登録したパッケージを使ってみる

まずはcomposer requireコマンドを実行してパッケージをインストールします。

composer require naopusyu/hello-world

今回は依存するパッケージはないので、上記を実行すると登録したパッケージだけダウンロードされますね。

hello-world % composer require naopusyu/hello-world
./composer.json has been created
Running composer update naopusyu/hello-world
Loading composer repositories with package information
Updating dependencies
Lock file operations: 1 install, 0 updates, 0 removals
  - Locking naopusyu/hello-world (1.0.0)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
  - Downloading naopusyu/hello-world (1.0.0)
  - Installing naopusyu/hello-world (1.0.0): Extracting archive
Generating autoload files
No security vulnerability advisories found.
Using version ^1.0 for naopusyu/hello-world

実行が終わったら、適当なサンプルファイルを作ります。

hello_world.php
<?php

require_once './vendor/autoload.php';

echo new \App\HelloWorld()->say . PHP_EOL;

最後に作成したファイルを実行します。

hello-world % php hello_world.php 
Hello World

動きましたね🎉

登録済みパッケージを更新する

公開したパッケージに何かしらの修正を入れた場合、新たにタグを付けることになります。
この場合、その都度Packagistにログインして、該当パッケージの画面にいき、Updateボタンを押す必要があり大変面倒な作業です。

しかし、事前準備に書いたPackagistとGithHubのアカウントの連携をしておくとタグが作成されると自動でPackagistの方にも反映します。
また、アカウントの紐付け以外にもGitHub Webhookに登録することで自動で反映することも可能です。

今回はGitHub Webhookの登録の方法を書いておきます。

GitHub Webhookの登録は該当リポジトリのSettingsにあるWebhooksから登録できます。

  • Payload URLには以下を入力します
    https://packagist.org/api/github?username={Packagist username}
  • Content typeapplication/jsonを選択する
  • SecretはPackagistのprofileの画面から取得できます
  • triggerJust the push event.を選んでおけば大丈夫です

Add webhookを押して登録完了です。

この後、新しいタグをつけてpushすると、該当パッケージに自動で反映できます。

git tag 1.1.0

Webhookの設定したことで、登録時に出ていた警告も消えていますね。

先ほどパッケージをダウンロードしたディレクトリでパッケージを更新してみると1.1.0がダウンロードできたので更新もできていますね。

hello-world % composer require naopusyu/hello-world
./composer.json has been updated
Running composer update naopusyu/hello-world
Loading composer repositories with package information
Updating dependencies
Lock file operations: 0 installs, 1 update, 0 removals
  - Upgrading naopusyu/hello-world (1.0.0 => 1.1.0)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 0 installs, 1 update, 0 removals
  - Downloading naopusyu/hello-world (1.1.0)
  - Upgrading naopusyu/hello-world (1.0.0 => 1.1.0): Extracting archive
Generating autoload files
No security vulnerability advisories found.
Using version ^1.1 for naopusyu/hello-world

まとめ

手順として複雑なこともなく、Composerパッケージの公開は思ったより簡単にできました。

作成したパッケージはHello Worldを返すだけの内容なので誰かに使われることはないと思いますが、今後なにか便利そうなものができたら、誰かに使われるパッケージを公開したいと思います。

GitHubで編集を提案

Discussion