Composerで目指せ公開プロジェクト

タグ: Laravel5.1LTS   Laravel  

Laravelリファレンス発売記念、販売促進アドベントカレンダーの2015年12月9日分です。

Laravelリファレンス」から溢れてしまい、スピンオフする電子書籍に取り込まれる予定のComposer編で、書ききれなかった部分を補足する記事です。載せきらなかった部分は、電子書籍に入る予定ですが、その内容に重なる部分もあります。

Composerに関しては、書いた内容が多すぎるため、自主的に半分に削りました。その後、全体の長さが2倍近くになることが判明し、「直接Laravelではないから」と電子書籍に回すことになりました。

その後、やはりComposerについて載せたいと言うことで、パッケージの依存解決と、繁用されるコマンドの部分のみ書籍に入れることになりました。

今回紹介する内容は、それと多少離れ、プロジェクトを公開する場合のメタ情報の書き方がメインです。

公開してみる意義

もし、便利なライブラリーやらシステムができたら、公開してみましょう。そうそう大人気は得られないでしょうが、それも経験です。

メインの流れとしてはGitHubに公開パッケージとしてpushし、Packagistで公開の設定をします。(GitHubでなくても良いのですが、やはりGitHubがなんと言っても主流です。)

「やたらに、『公開してみた』程度のプロジェクトが多くて困る」という意見もあります。しかしながら、GitHubもPackagistもそれを許しているのですから、とやかく言われるいわれはないのです。まず、公開してみなくては経験が積めません。(そもそも、Webがそうした世界です。誰でも自由に情報発信ができますが、人気のあるサイトはひと握りです。それと同じなのです。品質で制限すると、いつでも量が伸びなくなるのです。量が伸びないと、品質が上がらないのです。この世の常です。)

別に人気が得られなくても良いのです。勉強のために公開してみても良いのです。そうした中から、人気のあるプロジェクトが生まれてくるのです。(LaravelもTaylorさんの遊びから始まったことを思い出してください。)

できるだけ幅広く

Laravel専用のパッケージが多くなってきた時に出た意見は、「できるだけ特定のフレームワーク専用にせず、どんなプロジェクトでも使えるように。」といういうものです。(これは、有名な人が本人の弁によると「言い方を間違えた」多少攻撃的な言い回しで発信したため、Laravelユーザーの反感を買うことになりました。それを日本でLaravelアンチの人がわざわざ日本語で伝えたという、ネガティブな記憶がありますが、言っていることは正しいのです。)

Laravelにはサービスプロバイダーがあり、拡張もしやすくなっていますが、どうせ役に立つパッケージを作成するなら、Laravelという枠にとらわれず、より多くのフレームワークや状況で利用できるように作成するほうが、多くの人に使ってもらえるチャンスがあります。

ただし、「より一般的に作成する」のは、難易度は上がります。そのため、最初から「広く、幅広く」を狙わなくてもよいでしょう。それでも、「より多くの状況で使ってもらうにはどうするのか」という視点はどこかで持っていましょう。

Composerのメタ情報

Laravel限定の拡張機能であろうと、Laravel上で動作するシステムであろうと、Laravelに関係ないPHPライブラリーであろうと、まずはcomposer.jsonで公開に必要なメタ情報をしっかりと書く必要があります。

{
  "name": "ベンダー名/パッケージ名",
  "description": "このパッケージの説明(できれば英語で)",
  "keywords": ["framework", "laravel"],
  "authors": [
    {
      "name": "Ichiro Tanaka",
      "email": "ichirotanaka@example.com"
    }
  ],
  "license": "MIT",
  "type": "project",
  "homepage": "http://example.com",
  "support": {
    "email": "support@example.org",
    "issues": "https://github.com/ベンダー/パッケージ/issues",
    "source": "https://github.com/ベンダー/パッケージ",
    "docs": "https://github.com/ベンダー/パッケージ/blob/master/readme.md"
  },
…(後略)…

パッケージを公開するために最低限必要なのは、nameとdescriptionのアイテムです。それ以外のアイテムは必須ではありませんが、指定しておくとPackagistで表示されますので、より「使ってもらえる」可能性が上がります。

ベンダー名をまず決めましょう。通常は「誰が作成したものか」を指します。通常GitHubでコードを公開する場合、登録しているユーザー名です。私の場合"HiroKws"ですが、これを小文字にした"hirokws"がベンダー名となります。ユーザー名の代わりに「組織名(Organization)」を使うこともできます。ほかのGitリポジトリーサービスであればグループ名と呼ばれることもあります。Laravelが使用している"laravel"と"illuminate"もGitHubの組織名です。

ベンダー名を決めるときは、既存のものとダブらないようにします。通常、このベンダー名がGitHubなどのユーザー/組織名であり、Packagistのベンダー名であり、Composerでもベンダー名であり、PHPコードでは先頭の一文字を大文字にして、最上位の名前空間名として利用します。名前空間がクラス名の衝突を防ぐための機能であることを考えれば、当然最上位の名前空間は、他とダブらないことが重要になります。

GitHubのユーザー名や組織名と異なる名前を空間名の最上位として利用することは可能です。しかし、PSRの規約として名前空間名のトップは「ベンダー名として知られているもの(The fully qualified class name MUST have a top-level namespace name, also known as a "vendor namespace".)」である必要があります。ComposerはPSR−0とPSR-4のオートロード規約に対応していますので、特にベンダー名は他とダブらないように付ける必要があります。

GitHubの組織名を考えるときも、Packagistを見て、存在していない名前を付けましょう。私の場合、後で正直失敗したと思ったのは、GitHubのユーザー名に大文字を入れてしまったことで、ここは小文字だけにしておけば良かったと思います。(でも、まあ、アカウント作成したのはPSRの規約が決まる前ですなんですが。)それでも手間としたら、このベンダー名を指定する時に全部小文字で指定するだけです。名前空間にする場合は、先頭を大文字です。(正直、私自身公開したパッケージでは、よく考えずに名前空間のトップを決めていました。GitHubで調べ、他のベンダー名やパッケージ名でヒットしない、オリジナルな名前を使うようにしていました。自分のIDを先頭に付けるのは押し付けがましいと感じていたからです。その後、ベンダーの意義を考えなおし、アイデアが浮かんだら、オリジナルな組織名をまずGitHubで作成しています。もちろん、ベンダー名として、名前空間のトップレベルで使用できるようにです。)

ベンダー名の次のパッケージ名は、よく他とダブることがあります。しかし、ベンダー名が異なっていれば、パッケージ名が同じでも、当然別のパッケージとして扱われますし、名前空間の衝突を考える必要もありません。全く問題ありません。パッケージ名には好きな名前を付けましょう。

descriptionはPackagistでパッケージを検索する時に表示される説明文として利用されます。ですから、英語で書くのが基本です。

keywordsもPackagistのパッケージ検索時に利用されます。現在は余り重要視されていないようです。パッケージ検索が全文検索になったからだと想像しています。パッケージの内容のページで表示され、クリックすれば同じタグのパッケージがリスト表示されます。その程度です。

authorsは開発者のリストです。基本は名前のnameとメールアドレスのemailを指定します。それに付け加え、開発の役割が分担されているならばroleを追加し、developer、tester、translatorなどの役割を記述するもできます。homepageで個人のホームページを指定することも可能です。

licenseはこのパッケージのライセンスを指定します。Packagistでも表示されます。ライセンスを書いていないと、通常の著作物ということになり、他の人が自由に使用できません。ライセンス的には通常ReadmeかLicense.mdなどにライセンス条項を書いておけばOKなのですが、検索するページには自動的に表示されませんので、composer.jsonにもしっかり書いておきましょう。

typeはこのパッケージのタイプです。Composerが決めているのは、他のプログラムのためにインストールされる"library"と、CMSやLaravelフレームワーク、アプリケーションなど、他のプログラムのライブラリーとして使用される目的ではない"project"です。

もう2つ"metapackage"と"composer-plugin"もありますが、通常私達が作成するComposerコンポーネントはlibraryかprojectのどちらかになるでしょう。

それ以外にも自由に決めて良いので、たとえばLaravel専用の拡張として"laravel-extension"とか指定できます。ただ、こうした独自の指定方法は規約として決めておくべきでしょうし、Laravelはそんなことを求めていませんので、Laravel用の拡張だとしても"library"と付け、keywordsにlaravelを入れておくほうがよいかと思います。

homepageはこのパッケージのホームページです。GitHubでホームページを作成することができます。もしくは、GitHubのリポのURLやReadmeファイルのURLを指定することもあります。GitHubのWikiを使うこともできます。深く考えないで、一番情報がある場所、管理しやすい場所を指定しましょう。

supportはこのパッケージのサポートです。コンタクト用のemail、バグレポート等を受け付けるissues、ソースコードのありかを示すsource、ドキュメントの場所を示すdocsの4つは指定しておきましょう。

小さいパッケージであれば、コンタクトのemailも開発者のemailも皆さん自身のものになるでしょう。重複してもかまいません。ただし、でたらめなアドレスではなく、連絡が付くアドレスにしてください。もし、あなたのパッケージに脆弱性がある場合、見つけた人が直接コンタクトを取ってきます。脆弱性は公開されているissueシステムやバグ追跡システムでは報告しません。悪意のある第三者が、脆弱性が修正されるまでの間、利用することが無いように、まず直接連絡するのがルールです。

GitHubへホストするのであれば、issueを受け付けるように設定し、そのURLをissuesに指定すれば簡単です。同様にドキュメントもGitHubのページやWikiを利用して作成し、そのURLを指定できます。今回の例のように、Readmeに必要なことを全て記載しておき、表示URLを指定するのも一般的な方法です。

GitHubへホストしたパッケージのURLは、ソースの場所として指定できます。ですから、GitHubを使用し公開すれば、この4つを用意するのに手間はかかりません。

LaravelベースのWebアプリ

インストーラーとかを用意するのでなく、たとえばLaravelフレームワークをインストールするときのように、composer create-project ベンダー/パッケージ new-siteでユーザーにLaravelベースのWebアプリを公開する場合、Laravelのインストールディレクトリーに含まれていたファイルがそのまま公開対象になります。(LaravelのドキュメントのチュートリアルはGitHubでソースが公開されています。https://github.com/laravel/quickstart-basic このような感じで公開することとなります。)

つまり、Laravelに含まれるcomposer.jsonをあなたのアプリに合わせて変更する必要があります。「composer.jsonは変更して良いものなのか?」と悩む必要はありません。どんどん自分のパッケージのために変更しましょう。

ただ一点、ライセンスを"MIT"以外に変更する場合、Laravel自体はMITですからそこに含まれているファイルは全部MITライセンス下で公開されていることを思い出してください。新しいライセンスがMITと一緒に使用できないものであれば、そのままではライセンス違反になりますので公開できません。larave/laravelリポに含まれるファイル、つまり自分のパッケージとして公開するファイルは、全部自力で作り直す必要が起きます。

Illuminateとして公開されているLaravelのコンポーネントやその他の依存パッケージ、つまりComposerによりインストールされ、vendorディレクトリー下に配置されるパッケージのことではありません。それらは、それぞれ別々に各自が採用したライセンスにより公開されていますが、後からユーザーによりインストールされるもので、あなたの公開するパッケージに直接含まれているものではありません。ですから、依存パッケージとして利用しているComposerコンポーネントに関しては、頭を悩ます必要はありません。

自分のパッケージに直接含まれるファイルに関して、ライセンスに注意する必要があります。簡単なのはLaravelと同じMITのまま公開することでしょう。そしてReadmeにLaravelベースで、オリジナルのファイルはLaravel開発者のTaylor Otwell氏がCopyrightホルダーであることを明記しておきましょう。(もちろん、パッケージ作成者である自分の名前も忘れずに。)

公開まで…省略

あとはcomposer.jsonに必要なrequireやら、オートローディングの指定を書き、GitHubなどにホストし、Packagistにログインし…なのですが、これらの情報は既にWebにたくさんありますので、自分の作成するものにあった情報をご覧ください。

注意、バージョン

公開するパッケージにはバージョンを付けましょう。バージョンはcomposer.jsonに指定することもできますが、通常はGitのタグで指定します。

バージョンを付けないと、composerの扱いとしては「開発中」扱いになります。

"数字.数字.数字"か"v数字.数字.数字"の形式で付けます。もちろん数字が高くなるほど、新しいと解釈されます。

これらの数字のつけかたは、いろいろな方法や、個人の考え方があります。一応、セマンティク・バージョニングという「一番左は互換性を無くす場合にあげる、真ん中は新機能付ける場合、右端はバグフィックスなど」というやり方が、まあ常識的であります。

そして、パッケージの内容を変更し、GitHubに反映したら、タグのバージョンも上げ、忘れずにGitHubに反映してください。(通常は、自動的にPackagistに反映される設定にしているでしょう。そうでなければ、Packagist側でも更新する必要があります。)

バージョンを上げないと、あなたのパッケージを使用しているユーザーがcomposer updateをしても、更新されない羽目になります。(つまり、ちょっとした手直しであっても、バージョンを上げていくのが肝心です。一度つけたタグを削除し、他のコミットに付け直しても、その情報はユーザーには届かず、更新されません。)

これが面倒なため、いつまでもタグを付けないで公開する人もいます。タグを付けないでもブランチを"dev-ブランチ名"でrequireさせるのです。しかし、"dev"の部分が示すように「開発版」扱いになりますので、良くありません。

逆に言えば、あなたが公開するパッケージ、特にライブラリーとして公開する場合には、バージョンが付いておらず、正式版がないパッケージの使用を避けましょう。あなたのパッケージを利用する人が、"minimum-stability"の指定でパッケージ全体で使用する最低の安全度を下げたり、もしくはそのパッケージの依存度を指定させたりする必要が起きます。(使ってくれる人に、余計な手間をかけさせないということです。)

たとえば、正式公開前のものには0.0.0、0.0.1、…バージョンを利用し、正式公開になったらバージョン1.0.0を付け直すことはよく行われます。利用者は一番先頭の数字が0であることで、正式リリース以前のバージョンであることが分かります。Composerにとっては、バージョンが付けられているので、「開発中」として扱いません。

基本は特別な理由がない限り、Gitタグで自分のパッケージにバージョンを付け公開し、パッケージで利用するコンポーネントも、バージョンがきちんと付けられているライブラリーを利用しましょう。