🎼

Composerパッケージを作ろう その①

2020/12/08に公開

はじめに

PHPを使っていてComposerのお世話になっていない人はいないと思いますが、公開されているパッケージを使用するだけではなく、自作のパッケージを公開してやろうという人向けの記事になります。

OSS活動をしていきたいけど具体的な手順はどうなっているんだーと思っている人の一助になれば幸いです:blush:
(※自分もこれまでパッケージ公開などはやってきていなかったので、アドバイス等あれば喜びます)

temori/distancexport
スクリーンショット 2020-11-11 9.30.02.png
上記パッケージはDB間でデータを移行する必要があるテーブル名やカラム名が違うデータの移行の際にスプレッドシート形式で移行先のカラムと移行元のカラムを編集できたら便利だなーと思って作成しました。

最終目標

packagistに公開してcomposer require [パッケージ名]でパッケージがインストールできるまでを目指します。

環境構築

開発環境はいつもdockerで準備しています。
お好きな環境で開発すれば良いかと思います。

ちなみに自分は以下のリポジトリの環境で開発しています。
temori1919/docker-lamp

プロジェクト作成

まずパッケージ用のディレクトリをします。
最低限以下の様なディレクトリ構成でいいかと思います。

自分はpackageディレクトリの下にvendor名パッケージ名でディレクトリを作成していますが、ルートディレクトリがパッケージ名でも問題ないかと思います。

package
└── vendor名
    └── パッケージ名
        ├── LICENSE       # githubのリポジトリ内で作成することが可能です
        ├── README.md     # パッケージの概要を記述するので完成してから作成しても構いません
        ├── composer.json # 後述するcomposerコマンドで生成されるファイルです
        ├── .gitignore    # gitから除外したいファイルがあれば作成します
        ├── src           # パッケージのソースを格納するディレクトリです
        └── tests         # テストコードを格納するディレクトリです(なくてもOK)

ディレクトリを作成したら、composer initコマンドでcomposer.jsonを作成します。

外部パッケージを定義しているいつものあのファイルです。

$ cd path/to/package/vendor名/パッケージ名

# コマンドを実行すると対話形式でファイル作成が始まります
$ composer init
                                            
  Welcome to the Composer config generator  
                                            
This command will guide you through creating your composer.json config.

# ベンダー名/パッケージ名を入力してEnter(ここで入力したものが外部公開した時のベンダー名/パッケージ名になります)
Package name (<vendor>/<name>) [some/mypackage]:
# パッケージの概要を記述しますが空白でも構いません。(後述するpackagistの概要に表示される箇所になります)
Description []:
# 製作者、nでスキップしても問題ありません
Author [some <some@address.com>, n to skip]:
# 最小安定性、そのままEnterでも問題ありません
# 作成するパッケージの安定性を記述する箇所になります
# デフォルトは「stable」で使用できる値は「dev」、「alpha」、「beta」、「RC」、「stable」のみとなります
Minimum Stability []:
# パッケージのタイプ、そのままEnterでOK
# デフォルトが「library」(vendorの下にインストールされるタイプ)でそのほかに「project」、「metapackage」、「composer-plugin」があります
Package Type (e.g. library, project, metapackage, composer-plugin) []: 
# ライセンスのタイプ(用途にあうライセンスを指定してください)
License []:
# 使用する予定のあるパッケージを検索します
# とりあえず使用する予定はないのでそのままEnter
Would you like to define your dependencies (require) interactively [yes]?
Search for a package:
# こちらは上記のdevパッケージになります
# 使用予定のものがあればここで検索してもいいですが、後から追加でもOKなのでとりあえずEnter
Would you like to define your dev dependencies (require-dev) interactively [yes]?
Search for a package:

# コマンドに記述した内容の確認になります
# 問題なければEnter(あとでファイルを直接修正することもできます)
{
    "name": "some/mypackage",
    "license": "MIT",
    "require": {}
}

Do you confirm generation [yes]? 

パッケージディレクトリの直下にcomposer.jsonができていると思います。

mypackage/composer.json

これでディレクトリの準備ができました。

パッケージの処理を実装する

ディレクトリやダミープロジェクトの作成

srcディレクトリ配下にクラスやメソッドを作成していきます。

パッケージを開発する際はローカルのディレクトリにあるパッケージをcomposer requireして開発を進めていきます。

まず開発するパッケージをインストールするダミーのプロジェクトを作成します。
先ほど作成したパッケージ用ディレクトリと同階層になります。

├── package
└── dummy-project

※FWを使用してのプロジェクト作成でも問題ありません。

作成したプロジェクトに移動してcomposer.jsonを作成し以下を追記します。
※FWを使用してプロジェクトを作成した場合は、すでに配置されているcomposer.jsonに追記します。

cd dummy-project
    "repositories": [
        {
            "type": "path",
            "url": "../package/vendor名/パッケージ名"
        }
    ]

これでcomposer initの際に指定したベンダー名/パッケージ名

composer require ベンダー名/パッケージ名

コマンドを打てばローカルのディレクトリがパッケージとしてインストールされます。

composer.jsontypeを変更することにより、インストール先を変更することができます。repositoriesの指定がないと、デフォはpackagistからパッケージを検索します。
pathでローカルディレクトリからの読み込み、vcsでgithub等のリポジトリホスティングサービスから直接インストールなどインストール先を変更することが可能です。

詳しくは以下を参照してください。

https://getcomposer.org/doc/05-repositories.md#types

typepathにしてインストールするとインストールしたプロジェクト内のパッケージの格納されているvendorディレクトリにローカルパッケージディレクトリのシンボリックリンクが生成されます。

パッケージのコーディングを行う際はプロジェクト内のvendor以下のパッケージを変更すれば、プロジェクトと同階層に作成したパッケージディレクトリのソースに反映されるので、IDEを使用している時はコードジャンプ等ができて便利です。

クラスやメソッドの作成

ちなみに自分はパッケージ名でメインとなるクラスを作成しています。

今回のパッケージだと以下の様な命名や構成になります。

├── LICENSE
├── README.md
├── composer.json
├── phpunit.xml
├── resources
│   ├── assets
│   │   ├── css
│   │   │   ├── jexcel.css
│   │   │   └── jsuites.css
│   │   └── js
│   │       ├── jexcel.js
│   │       └── jsuites.js
│   └── views
│       └── index.php
├── src
│   ├── DataBases
│   │   ├── BaseDriver.php
│   │   ├── Connect.php
│   │   └── Drivers
│   │       ├── Mysql.php
│   │       └── Pgsql.php
│   ├── Distancexport.php
│   ├── Provider.php
│   └── Renders
│       └── AssetResponse.php
└── tests
    └── DistancexportTest.php

Distancexport.phpがパッケージの起点となるクラスファイルです。

またresourcesディレクトリは今回のパッケージにはviewを描画する必要があったのでディレクトリを作成しています。

クラスを作成したらパッケージのcomposer.jsonにautoloadの設定を追記します。

{
    "name": "some/mypackage",
    "license": "MIT",
    "require": {},
    "autoload": {
        "psr-4": {
            "Some\\Mypackage\\": "src/",
            "Some\\Tests\\": "tests/"
        }
    }
}

これでsrc配下がSome\Mypackageのnamespaceでオートロードされます。

testsに関してはディレクトリ配下にテストコードが格納される前提なので、Some\Testsのnamespaceでオートロードされます。

またクラスを作成する際に命名するnamespaceですがオートロードで設定したnamespaceでないとファイルが読み込めません。

パッケージに実装するnamespaceを記述するファイルにはcomposer.jsonに記述した通りのnamespaceをつける必要があります。
(※上記例でいうとSome\Mypackage\ClassName

また外部のパッケージが必要な場合はrequireに記述すればプロジェクト側でこのパッケージをcomposer requireもしくはinstallした際にインストールしてくれます。

README.mdを作る

READMEを作成します。

自分は主に以下の様な項目を記載する様にしています。

  • パッケージ名
  • バージョンやライセンス等を表示するバッジ
    視覚的にわかりやすいし何よりカッコイイ:smiley:
  • 概要
    パッケージの概要を記述します
  • パッケージにUIがあればgifアニメや画像
    UIがあるものなら画像などがあった方がわかりやすいと思います。また、作成した画像でもいいかもしれません。
  • 目次
    各見出しのリンク付きの目次を配置します。
  • 特徴
    パッケージの特徴です。
  • 要件
    対応するバージョンなどを記載する箇所になります。
  • インストール方法
    パッケージのインストール方法です。
    コピペできる様にコマンドで記述します。
  • 使い方
  • ライセンス

今回公開したパッケージは以下の様な項目を記載しています。
https://github.com/temori1919/distancexport/blob/master/README.md

バッジに関しては以下のサービスを使用しました。

shields

packegistに公開してあるパッケージなら簡単にバッジを作成することができます。

もちろん公開していなくても作成できるバッジもあります。

スクリーンショット 2020-11-20 9.27.09.png

上記はpackagistのversionになりますが、公開されているベンダー名とパッケージ名を入力するとmdやhtmlでURLを生成してくれます。

バージョンに関してはpackagistに公開後でないと生成できないので、パッケージを公開し、後述するバージョンをタグ付けしたのちに作成することになると思います。

また、バッジのスタイルや文言を変更することが可能です。

GitHubにリポジトリを作成してpushする

リポジトリにソースをpushしましょう。
pushした後にLICENSEファイルを作成します。

Create new fileを押下し新しいファイルをGitHub上で作成します。
ファイル名にLICENSEと入力するとライセンスファイルのテンプレートが選べる様になります。
スクリーンショット 2020-11-20 9.37.45.png

後は用途にあったライセンスを選択してファイルを生成します。

タグでバージョンを指定する

tags->Create a new releaseで以下の様なタグ作成画面に遷移すると思うので、タグを生成していきます。

スクリーンショット 2020-11-30 8.54.27.png

Tag versionを指定します。

自分はv1.0.0からスタートする様にしています。
vがあってもなくても問題ありません。

composerはv付きでもバージョンとして認識します。

Tag versionの横にTargetブランチが選択されていますが、masterブランチの現時点での最新コミットが今回のタグ付けしたバージョンになります。

タイトル、詳細内容等あれば記述しますがなくても問題はありません。

packagistに公開する

最後にpackagistにGitHubのリポジトリを公開します。

アカウントがなければ作成してください。
GitHubアカウントでもログインすることが可能です。

スクリーンショット 2020-11-30 9.46.12.png

ヘッダーにあるSubmitボタンからパッケージを送信するページを表示します。

リポジトリのURLをRepository URLに記載してCheckボタンを押してください。

これでGitHubのリポジトリとpackagistが紐付来ました。
GitHubで追加したタグ情報もpackagistのパッケージバージョンとしてリンクする様になります。

リポジトリに追加してあるREADME.mdもpackagistのパッケージTOPページに反映されます。

GitHubのWebhookにpackagistのapiトークンを登録する

GitHubのWebhookにpackagistのapiのURLを登録します。

Webhookを活用することでGitHubのリポジトリを更新した際に自動でpackagist側に変更を反映させることができる様になります。

スクリーンショット 2020-12-03 9.39.12.png

Show API Tokenを押してトークンを表示してください。
その下のthe docsのリンクを押すとGitHubのWebhookの登録方法が表示されます。

上記のドキュメントに記載されているURLを表示したトークンを使ってGitHubにWebHookを登録します。

スクリーンショット 2020-12-03 9.46.47.png

ドキュメントに記載されている通りに入力してください。

これで公開に伴う全ての作業が完了しました。

最後に

手順を追ってみると、パッケージの公開はそこまでハードルの高いものではないと思います。

次回はLaravelのパッケージを公開する手順に続きます。

Composerパッケージを作ろう その② - Laravelパッケージ編

Discussion