apigen

guzzleで使われていたApiGenが良さそうだったので、試してみた。これはイイ!php-coverallsのAPI docを試しに作ってGitHub Pagesに載せてみた。

Which one is better?

PHPでは、他にも使えるツールがいくつかある。PHP用のツールとしては、以下が有名どころなんじゃないかと思う。括弧内の数字はGitHubでのスターの数。

ツール composer PHP
phpDocumentor2
GitHub (823)
5.3.3+
ApiGen
GitHub (362)
5.3.0+
phpDox
GitHub (140)
× 5.3.3+
PHPDoctor
GitHub (89)
5.2.0+

GitHubのスターの数はphpDocumentor2が一番多い。PEARのAPI docでも使われているphpDocumentorの後継ツールだ。しかし、以前試した時には、Page level docを要求しておきながら、どこに書いてもエラーになったりと、中々安定しない印象だった。生成速度はv1と比べてだいぶ速い。

phpDoxはTemplate for Jenkins Jobs for PHP Projectsでも採用されているツールだ。ファイル判定がFILEINFO_MIMEのため、.phpのファイルであってもC++のファイルだと勘違いされることが多々あった。この部分だけ修正すれば使えないこともないが、@inheritdocに対応していないので、eclipseでPDTを使っている自分としてはあまりメリットがない。さらにPackagistに登録されていないため、composer installしようとすると、PEARのめんどくさい書き方をしなければいけないのが(ry

PHPDoctorは、以前にもphpDocumentorの乗り換え先を検討したときに使用してみたが、ドキュメントの生成が中々速くていい感じだった。最近になって、composerに対応したようだ。

ApiGen

  • PHP 5.3+
  • composer対応!
  • @inheritdoc対応!
  • まさかのGoogle Analytics対応

完璧じゃないか。guzzleのAPI docを見た感じだと、デフォルトのテンプレートで十分読みやすそうだ。

Good

試してみて分かった良いところ。

  1. 生成速度はphpDocumentor2と同程度
  2. checkstyle形式でエラー一覧を出力可能
  3. vendorライブラリを読み込みつつも、メインプロジェクトを設定可能

php-coverallsで試してみたところ、phpDocumentor2とApiGen 2.8.0は25秒前後で完了した。

個人的に一番良かったのは、3番目。他のツールが対応していない部分だ。

例えば、メインプロジェクトのクラス(My\FooApplication)が、依存ライブラリのクラス(Vendor\Application)を継承していたとする。この場合、Vendor以下のクラスも生成対象に含めてしまうと、API docのトップページにはMyVendorも一覧表示されてしまう。Myを含めない場合、@inheritdocの参照先が無くなってしまい、ドキュメントに反映されない。しかし、依存ライブラリに関するドキュメントではないので、一覧にはメインプロジェクトだけを載せたい。

そんな時に、--mainオプションに名前空間の先頭を指定しておくと、index.htmlにはこの名前空間に含まれるクラスだけが一覧表示される。この例だと、MyをしておくとVendor以下のクラスは一覧表示されない。さらに、依存ライブラリについてはサイドバーから参照可能になっている。My以下のクラスとVendor以下のクラスはここでまとめて参照可能だ。

Configuration by NEON format

ApiGenの設定ファイルはNEONフォーマットになっている。

コマンドオプションの名前がそのまま設定ファイルのキーになるようだが、ハイフンが入っているオプション名の場合、エラーとなってしまった。設定ファイルにどう書いたらいいのだろうか。もちろんコマンドオプションに指定すると大丈夫だった。

Markdown in doc block

phpDocumentor2、phpdoxではdoc block内でmarkdownが出来たりする。ApiGenはまだあまり対応してなさそうだ。コード例なんかが書いてあるdoc blockだと、一行にまとまって出力されてしまった。*でリストを表現している場合はうまく解釈された。

例えばこんなの。

class Test
{
/**
* Hello.
*
* $t = new Test;
* $t->hello(); // => "hello"
*
* @return void
*/
public function hello()
{
echo "hello";
}
}

この場合、ApiGenだと、$t = new Test; $t->hello(); // => "hello"と一行になってしまう。

/**
* Return default options.
*
* * opt1
* * opt2
*
* @return array Default options.
*/
function getDefaultOptions()
{
return array('opt1', 'opt2');
}

リストはうまく解釈できて、これはul>liで出力される。

Conclusion

  • ApiGenいいよ!

post commitとかで自動的にAPI docを更新できると便利だと思うんだけど、どうしよう。いまいち、gh-pagesブランチの運用方法が分からない。もう少し調べておきたい。

PSR-?

ツール毎にタグの対応状況が異なっているが、元になっているのは、おそらくphpDocumentorで対応していたタグなんじゃないだろうか。PHPDoc referenceを見ると、phpDocumentor2でも、ほとんど対応されているんじゃないかと思う。PSRでも標準化して欲しいなーと思ったりした。IDE側の対応もしやすくなるだろうし、アノテーションとして利用しているフレームワークやライブラリもあるわけだし。PackagistでもAPI doc見れると便利だと思うんだけど。

アノテーションパーサーもC extensionで作ってるのないのかなーと思って探してみると、Phalconのannotationsがそれらしいのを作ってた。

PSR-FIG mailing list

PHP-FIGメーリングリストを見てみたら、PHPDocの仕様について、昨年の9月から12月まで、議論されていたらしい。

全てのコメントを追いきれていないため、現在のステータスがよく分からないが、このディスカッションの中では、phpDocumentorのMike van Rielがドラフトを作っていた。

@varはdeprecatedで、代わりに@typeを使えと書いてあるが、phpDocumentorもApiGenも対応してないし、eclipseも対応していない。どうなるんだろうか。他には、@category@subpackageがdeprecatedになっているようだ。fluent APIの実装が増えてきたことを反映してか、戻り値のselfタイプについても言及されている。

また、メーリングリストの中でdoc blockのタグについて、いくつか議論されていた。