PHP CS Fixer v2 でもっと快適PHPライフ
2014年に書いた PHP CS Fixer の記事 が今でも読まれているのですが、2016年末にリリースされた PHP CS Fixer v2.0 で後方互換のない変更が多く入っており情報が古くなっているため、改めて v2 について書いてみようと思います。なお現時点での最新版は v2.1.2 となります。
PHP CS Fixer とは
PHP CS Fixer は PHP コードをコーディング規約 (CS = Coding Standards) に沿って補正してくれるライブラリです。歴史を辿ると、元々は Symfony のプロジェクトリードの fabpot 氏が作成したもので、 PSR-½ 、あるいは Symfony のコーディング規約 に沿ってコードを補正する機能が実装されています。
チームでコードを書くときはコーディング規約に沿って書くのが大前提ですが、例えばコードレビューをするときにいちいちコーディング規約の指摘をするのも不毛ですし、かといってメンバーが全員 100% 守れるかというとそれもなかなか大変なわけですが、 PHP CS Fixer を導入することでコーディング規約に沿ったコードに自動変換をかけられるためそういったわずらわしさから解放される、とてもすばらしい仕組みなわけです。
基本的にはコマンドラインツールとして提供されていて、ファイル単位や、特定のディレクトリ以下に適用するなど、 CLI での操作に慣れていればとてもかんたんに使うことが可能です。今日ではメジャーなライブラリとなっており、主要な IDE との連携も様々用意されています。
前回の記事では、 Git のコミットフックで補正する方法を書きましたが、現在僕は保存時に都度 PHP CS Fixer で補正をするように IDE を設定して使っており、今時のだいたいの PHPer は IDE でコード書いてると思うので保存の際に自動補正という結論でよいと思います。
PHP CS Fixer v2 の変更点と使い方
前回の記事の時点では v1.2 でしたが、 v1.13 を経て現在は v2.1 までリリースされています。正直あまり細かくは追っておらず、ある日バージョンアップしたら v2.0 になって色々動かなくなったので、改めて README に目を通した程度なので、ざっくりとした解説となります。
これまでのバージョンアップの流れを見ると、コア機能自体に大きな変更はなく、拡張性・柔軟性の向上と、ルールの細分化・多様化といったことが主な変更内容に見受けられます。
レベル/フィクサーからルール/ルールセットに
v1.x は PSR-½ といったレベル (Level) の設定と、補正項目に当たるフィクサー (Fixer) でコーディング規約の設定をしていましたが、これらの扱いが「ルール (Rule) 」と「ルールセット (RuleSet) 」に変更されました。1つ1つの補正ルールと、複数の補正ルールの集合という形となり、再帰的なルール管理ができる他、複数のルールセットを適用できるため、より柔軟なルールの管理ができる構造になっています。
再帰的なルール管理とは、例えば 「Symfony」というルールは「PSR-2」を内包し、「PSR-2」は「PSR-1」を内包する、といった具合で活用されています。
複数のルールセットの適用については、ルールセットもルールの1つとして設定するような仕組みになっており、例えば次のコマンドのように「@ で始まっているのがルールセット」「それ以外を単一のルール」として --rules オプションで一括設定できるといったものです。
(ちなみに v1 で level と fixers を分離したのは僕だったりします)
$ php-cs-fixer fix /path/to/src --rules='@PSR2,@MyCompanyRuleSet,my_project_rule'
PHP のバージョンアップ用のマイグレーションルール (@PHP71Migration など) も用意されており、この構造変更により使い方の幅が広がりました。
ルールの一覧は README 、 v1 からルール名が変更されたものの確認は UPGRADE をご覧ください。
挙動が変わる恐れのあるルールかどうか区別できるように
ルールの中には挙動が変わる恐れがあるもの(リスキーなルール)があります。例えば ereg_to_preg は ereg 系関数を preg 系関数に置き換えるというルールです。こういったルールについては risky というフラグが設定されており、 --allow-risky オプションをつけて呼び出さないと実行に制限がかかる仕様になりました。
名前空間の変更
名前空間が Symfony\CS から PhpCsFixer に変更されました。前回の記事で GitHub のリポジトリオーナーが FriendsOfPHP に移管された話を書きましたが、コード側も Symfony から独立したものになりました。合わせて Composer での名称が fabpot/php-cs-fixer から friendsofphp/php-cs-fixer になっています。
.php_cs.dist の導入
プロジェクトごとのルールの設定を .php_cs というファイルで管理できるようになっていましたが、各自の環境ごとにカスタマイズできるよう、標準設定としての .php_cs.dist と個別設定用の .php_cs という扱いで分けられるようになりました。PHPUnit の phpunit.xml.dist なんかと一緒ですね。プロジェクトのルートディレクトリに .php_cs があればそれを、なければ .php_cs.dist を参照します。
Git でプロジェクト管理をしている場合、 v1 までは .php_cs ファイルを作成してリポジトリに格納していましたが、 v2 を使う場合は .php_cs.dist としてリポジトリに格納しておき、 .php_cs は .gitignore に指定しておきましょう。
.php_cs.dist の書き方について
改めて .php_cs.dist の書き方を見てみましょう。まずライブラリの名前空間が PhpCsFixer に変更されています。ルールの設定は setRules() で行いますが、設定したいルール名を配列のキーに、 true で有効、 false で無効となります。ルールによってはオプションの設定もできるようになっています。
ちなみにオプション付きのルールをデフォルト設定で有効化したい場合は [] を指定するのではなく true を設定します。気になって実装を見てた感じだと、 [] を渡すと false に変換されて無効になるようでした。
CLI の --allow-risky オプションに相当するのが setRiskyAllowed() です。デフォルトでは false なので、有効にしたい場合は true にしましょう。
<?php // .php_cs.dist namespace PhpCsFixer; return Config::create() ->setRiskyAllowed(true) ->setRules([ '@PSR2' => true, 'single_import_per_statement' => false, 'array_syntax' => [ 'syntax' => 'short', ], )]) ->setFinder( Finder::create() ->exclude('resources') ->in(__DIR__) ) ;
ルールの一部解説
ルールは PSR や Symfony のコーディング規約に定義されたものを細分化して定義されていて様々な種類があらかじめ用意されています。また、特定のコーディング規約に含まれていないルールもあるため、余裕がある方は README に書かれているルールを一通りチェックしてみるとよいかと思います。 ただ、正直 README だけだとどういう挙動になるのか判断つかないものもあって、 テストケース を確認しながら設定していったので、この辺はもうちょっと充実していると助かりますね。
(追記)
@fivestr @fivestr describe <name>でルール詳細が分かりますよ!
— Akihito Koriyama (@koriym) 2017年3月30日
describe コマンドなるものを教えていただきました。実行結果イメージを確認できるのでとてもわかりやすいですね。

(追記おわり)
せっかくなのでいくつかのルールをピックアップして紹介してみます。
ちなみにルールを適用した場合に手元のコードがどうなるのか確認したい時は、 CLI で --dry-run オプションと --diff オプションをつけて実行すると適用した場合の差分が確認できます。
$ php-cs-fixer fix /path/to/src --dry-run --diff
@PSR1, @PSR2, @Symfony, @Symfony:risky: 標準ルールセット
PSR-2 にリスキーなルールはありませんが、 Symfony コーディング規約は一部リスキーなものを含んでいるため、リスキーなものを含む Symfony のコーディング規約を指定する場合は2つのルールを設定します。
<?php return Config::create() ->setRules([ '@Symfony' => true, '@Symfony:risky' => true, ]);
ちなみに僕は基本的に PSR-2 をベースにその他のルールから必要な分だけピックアップして使うようにしています。 Symfony のコーディング規約は比較的細かく、以前指定していた際に思わぬタイミングで変更が入ったり、バージョンアップで挙動が変わったりと煩わしいケースがあったので、こだわりがある人は PSR-2 + 必要なルールを定義すると安定します。
@PHP70Migration, @PHP71Migration: PHP のマイグレーション用ルールセット
PHP のバージョンアップに追従する用のルールセットもあります。この辺はバージョンあげる際に CLI で実行して差分を見るとかがよいのかなと思いますが、あんまり大したことはしてないので一応あるくらいでみておくとよいでしょう。
array_syntax: 配列の表記を array() or [] に統一
配列の表記を統一するルールです。 v1 の short_array_syntax を設定したい場合は、 syntax オプションを 'short' にします。
<?php return Config::create() ->setRules([ 'array_syntax' => [ 'syntax' => 'short', ], ]);
binary_operator_spaces: => や = のアライメント
連想配列や定数・変数定義で = や => の位置揃えに関するルールです。 align_double_arrow と align_equals の2つのオプションがあり、 true で揃える、 null で何もしない、 false で揃えない(方向に補正)となります。デフォルトではどちらも false で、 @Symfony だとデフォルトで有効です。
どちらもデフォルトで false となっており、
下記の例は => だけ揃えて、 = は何もしないという指定です。
<?php return Config::create() ->setRules([ 'binary_operator_spaces' => [ 'align_double_arrow' => true, 'align_equals' => null, ], ]);
blank_line_before_return, function_typehint_space, method_separation: 空白や空行の設定
return の前やメソッド定義の間は空行を入れるとか、タイプヒントと変数の間にはホワイトスペースを1つ入れるとか、リーダビリティに関するルールです。この辺は @Symfony で有効になっていますが、可読性のためにも基本有効にしておくとよいと思っています。
だいたい、タイプヒントと変数定義の間にホワイトスペースを入れるとか当たり前だろくらいに思いますけど、用意されているルールにはこういう当たり前だろって思うようなものもたくさんあり、だからこそ確実に設定しておきたいところです。
<?php return Config::create() ->setRules([ 'blank_line_before_return' => true, 'function_typehint_space' => true, 'method_separation' => true, ]);
header_comment: PHP ファイルの共通コメント設定
コピーライトの表記などをすべてのファイルに共通で記載することができるルールです。たとえば公開用のライブラリでライセンス等を明記しておきたいとか、社内のルールで全てにコピーライトを記載する必要があるとか、あるいは自己顕示欲が強い方とかは活用するとよいでしょう。
<?php $header = <<<'EOF' (c) Ancar Inc. EOF; return Config::create() ->setRules([ 'header_comment' => [ 'header' => $header, ], ]);
no_unused_imports, ordered_imports: インポートの整理
no_unused_imports は未使用の use 文の削除、 ordered_imports は use 文のソートを行うルールです。 use 文が整理されていた方が依存状況が確認しやすいため、有効にしておくことをおすすめします。
<?php return Config::create() ->setRules([ 'no_unused_imports' => true, 'ordered_imports' => true, ]);
ちなみに ordered_imports を有効にした場合、 グルーピングしている部分もソート対象になります。
<?php // before use Model\{User, Article}; // after use Model\{Article, User};
return_type_declaration: リターンタイプヒントのフォーマット
PHP 7.0 から導入されたリターンタイプヒントの書式ルールです。有効にすると function (): string のように : の後ろに1つホワイトスペースが入るようになります。 space_before オプションを 'one' にすると function () : string のように : の前にもホワイトスペースが入ります。
<?php return Config::create() ->setRules([ 'return_type_declaration' => true, ]);
single_import_per_statement: インポートを1クラスごとに展開
1つの use 文につき1つのクラス定義のみ行うようにするルールです。これは @PSR2 に含まれているルールですが、 PSR-2 は PHP 7 が考慮されておらず、{...} を使ってグルーピングしているものも展開されてしまうため、僕はあえて無効にしています。
その辺は PSR-12: Extended Coding Style Guide の策定以降により細かく調整されるかと思いますので、 PSR-12 を待ちましょう。
<?php return Config::create() ->setRules([ '@PSR2' => true, 'single_import_per_statement' => false, ]);
まとめ
PHP CS Fixer も v2 になって基本的な API 周りはだいぶ固まったかなという印象ですね。この記事で解説した以外にも設定項目があったり、様々なルールが定義されていますので、ぜひ自分にあった形で活用してもらえるとよいなと思います。
あとは PSR の方で、 PHP 7 対応のコーディング規約が待たれるところですね。あまりそっちも追ってるわけではないためどうなるのか不明ですが、何れにしても秩序をもたらす方向に歩んでいることはとてもすばらしいと思います。
コーディング規約を詳細に書いたドキュメントを用意する以上に .php_cs.dist にコーディング規約が定義されている状態の方が建設的ですし、 Coding Standards as Code な世界をエンジョイしましょう。
最後に、今僕がプロジェクトで使ってる .php_cs.dist を参考までに載せておきます。割と細かく指定があり全部解説はできないのですが、適用ルール把握のために PSR-2 + 個別ルールで設定・リスキーな補正はしない・言わなくてもやるようなルールであっても設定する、というポリシーで用意したため、チームの環境や文化に合わせて活用するとよいでしょう。
PHP CS Fixerで快適PHPライフ
2017/03/30 追記
新しいバージョン (v2.0) の記事を書きましたのでこちらもご覧ください
この記事は PHP Advent Calendar 2014 の8日目の記事です。
コーディング規約が守れない方とお悩みの方も、チームメンバーがなかなか守ってくれないとお悩みの方も、 PHP CS Fixer があればもう安心。PHP CS Fixer が PHP コードをコーディング規約に沿って整えてくれるので、秩序ある PHP ライフが約束されるでしょう。
そんなこんなで PHP Advent Calendar 2014 の 8 日目ですね。みなさんこんにちは、 fivestar こと小川です。いつのまにかクロコスがなくなって Y の人になっちゃいましたね。
昨今は PSR (PHP Standard Recommendation) の普及も進み、PHP 界隈にも統一感が訪れてきていますね。会社でコーディング規約を定める際、 PSR を基準とするところも増えてきていることでしょう。
ただ、コーディング規約を定めても、うっかり規約に沿わないコードを書いてしまう場合もあったり、コーディング規約の細部まで覚えられない場合や、どうしてもクセで間違えてしまう、なんて方も少なくないと思います。
組織によってはコードレビューを積極的に取り入れているところもあるかと思いますが、いちいち規約違反を指摘するのはもううんざり、なんて方もいるのではないでしょうか。
そんなときは PHP CS Fixer の出番です。
PHP CS Fixer とは
PHP CS Fixer (PHP Coding Standards Fixer) とは、その名の通り PHP コードをコーディング規約に沿うよう修正してくれるツール です。開発は活発に行われており、11月には v1.0 がリリースされました。現時点の最新バージョンは v1.2 がリリースされています。
PHP CS Fixer には標準で PSR-0 、 PSR-1 、 PSR-2 、および Symfony のコーディング規約 用の修正プログラムが用意されており、これらに準拠する場合はそのまま利用可能です。
ちなみに Symfony のコーディング規約は PSR-0/½ に準拠した上でさらにいくつかの規約を追加したもので、それらの上位規約として扱われ、 PHP-CS-Fixer のデフォルト に設定されています。
元々 Symfony のコアデベロッパーの Fabien Potencier 氏が開発したもので、前まで GitHub の fabpot ユーザが管理していたのですが、 最近 FriendsOfPHP に移管されたようです。
インストール
インストール方法は ドキュメント にいくつか書いてありますが、僕は Composer でインストールしてます。
% composer global require fabpot/php-cs-fixer Changed current directory to /home/fivestar/.composer Using version ~1.2 for fabpot/php-cs-fixer ...
Composer でインストールすると、 php-cs-fixer コマンドが利用可能になります。
ちなみに僕は ~/bin を Composer の bin-dir に設定してますが、デフォルトでは ~/.composer/vendor/bin あたりに入ると思うので Composer でインストールする場合は適宜パスを通す必要があります。
% composer config --global bin-dir "~/bin"
使い方
サンプル用に次のコードを用意します。これは PSR-2 の「名前空間の宣言直後に空行を入れる」「ブレス({ })は改行する」という2点に違反している状態です。
<?php namespace Sample; class Dummy { }
このファイルが配置されたディレクトリ上で php-cs-fixer の fix コマンドを実行すると対象に修正が行われます。 --dry-run オプションをつけることでドライランも可能です。次の例では対象を . にしているため、ディレクトリに含まれるすべての PHP ファイルが対象となります。
% php-cs-fixer fix . --dry-run --verbose --diff
F
Legend: ?-unknown, I-invalid file syntax, file ignored, .-no changes, F-fixed, E-error
1) Dummy.php (line_after_namespace, braces)
---------- begin diff ----------
--- Original
+++ New
@@ @@
<?php
namespace Sample;
-class Dummy {
+
+class Dummy
+{
}
---------- end diff ----------
Fixed all files in 0.103 seconds, 5.250 MB memory used
level / fixers オプションで修正項目を制御する
デフォルトで (PSR-0/½ を含む) Symfony のコーディング規約に沿うよう修正が行われますが、内部的には項目が細分化されているため、例えば Symfony を基準にするが一部の項目は除外したいとか、 PSR-2 を基準に一部 Symfony の規約を追加したいとか、細かな制御も可能です。
項目の名称とか内容とかはたくさんあって書ききれないので ドキュメント を参照してください。ここを見るとどの項目がどの規約に準拠した内容かも確認できます。
前述のサンプルで取り上げた「名前空間の宣言直後に空行を入れる」「ブレス({ })は改行する」はそれぞれ「line_after_namespace」「braces」という名前の項目になっています。 fix コマンドに --verbose オプションをつけるとどの項目が適応されたか一目でわかるので参考になるかと思います。
PHP CS Fixer では psr0 < psr1 < psr2 < symfony のようにレベルわけされており、上位は下位を含む扱いとなっています。そのため PSR-0 および PSR-1 の項目のみで修正を行いたい場合、次のように --level=psr1 を指定すると、 PSR-0 および PSR-1 に分類される項目のみが実行されます。
% php-cs-fixer fix . --level=psr1
さらに psr1 に加えて line_after_namespace 項目を指定したい場合は --fixers=line_after_namespace を指定します。
% php-cs-fixer fix . --level=psr1 --fixers=line_after_namespace
psr2 から braces と visibility を除いた項目のみ実行したいといった場合、項目名の先頭に - をつけて指定します
% php-cs-fixer fix . --level=psr2 --fixers=-braces,-visibility
このように level / fixers オプションを組み合わせることで、組織やプロジェクトごとの規約に沿った修正が実現できます。
.php_cs による設定管理
これらの指定は毎回しなくても、 .php_cs ファイルを用意することでデフォルトの挙動を設定しておくことが可能です。たとえば前述の最後のコマンドを設定化すると次のようになります。
<?php return Symfony\CS\Config\Config::create() ->level(Symfony\CS\FixerInterface::PSR2_LEVEL) ->fixers(['-braces', '-visibility']) ;
.php_cs ファイルが配置されたディレクトリ上でコマンドを実行するか、 --config-file オプションで .php_cs へのパスを指定すると .php_cs が読み込まれるようになります。設定ではこの他にも、検索対象のファイルの指定や自前の項目の追加なんかも可能です。 ドキュメント にもう少し詳しく使い方が書いてあるのでやりたいことが他にある方は見てみるとよいでしょう。
基本的な使い方はこの辺を覚えておけば十分かと思います。あとはどの項目を適応するかの選択かなと思います。
一応、項目のロジックは自分で追加/拡張できるんですけど、トークン化したコードを正規表現なんかも駆使してゴリゴリやってるので、まあその辺用意するよりは素直に PSR や Symfony の規約に合わせちゃうのが楽だと思います。せっかく標準化を進めてるわけですからね。
もし組み合わせた場合の挙動を詳しく知りたい方がいたら、 ConfigurationResolver のテスト を見てみるといいかと思います。
ちなみに以前に「追加の指定と除外の指定を同時にした場合にうまく適応されないバグ」があって、実はその辺を僕が Pull Request を送って修正した んですけど、ちょろっと修正するつもりがオプションとか設定関連なんかをついでにってことであちこち修正させられて、結局1ヶ月くらいかけてやりとりしながらなんとか取り込まれたという思い出がありまして、そんなこともあったので今回このネタにしたんですけど、せっかくなので記事の最後に思い出話も書いておきますので興味ある方は読んでみてください。
PHP CS Fixer を Git のコミットフックに設定する
PHP CS Fixer が使えるようになったからといって実行されないと意味ないので、エディタの保存時に実行するようにするとか、何かにつけて実行されるようにしておくのがよいかと思います。
クロコスのときは、 Git のコミットフックでコミット対象のファイルに対して PHP CS Fixer が実行されるように設定していました。一応 Gist に pre-commit ファイルを置いておきます。ちなみにオプションの指定は適当です。使われる場合は好きなように変えたり、 .php_cs ファイルを用意するのがよいかと思います。
https://gist.github.com/fivestar/7b2491c633d7476fa33f
元々 sotarok が GREE 時代に書いていた、コミット対象に php -l を実行するフックを拡張したもので、対象にコーディング規約違反があると、修正した上で diff を表示してコミットを中止する、ということを行っています。中止しているのは、以前想定外の修正が行われてプログラムがバグったことがあったので内容を確認してから add するなり修正するなりしてね、という意図があるためです。
% git add Dummy.php
% git commit
CS fixed:
F
Legend: ?-unknown, I-invalid file syntax, file ignored, .-no changes, F-fixed, E-error
1) /home/fivestar/sample/Dummy.php (line_after_namespace, braces)
Fixed all files in 0.121 seconds, 5.250 MB memory used
diff --git a/Dummy.php b/Dummy.php
index 62721b7..5e5873a 100644
--- a/Dummy.php
+++ b/Dummy.php
@@ -1,4 +1,6 @@
<?php
namespace Sample;
-class Dummy {
+
+class Dummy
+{
}
----
git pre-commit hook error
...
エディタで設定するかどうかは基本各自に任せていたので、最低限これを入れて防げるようにだけしていました。一応クロコスのときはリリース前に必ずコードレビューが入るようにしていたので、そこで規約違反見つけたら設定漏れてるかどうか確認したりはしていました。
このようにどこかのタイミングで必ず実行されるようにしておくと、コードレビュー時に最低限規約に沿った状態から始められるので余計なチェックをしなくて済むのでおすすめです。
一応ドキュメントに エディタ用プラグインリスト があるのでエディタに設定しておきたい人はチェックしてみてください。
Pull Request 送った時の話
蛇足かもしれませんが、前にちょこっと触れた通り、 Pull Request を送った時の話を少し書いてみます。
repo owner の話
このプロジェクト、 keradus ってポーランド人が活発に動いていて、彼とずっとやりとりしていたんですけど、彼についてすばらしいなと思ったことがありまして。彼は基本的にこちらの活動を褒めた上で、指摘や要望をあげるんですよね。あと1週間くらい修正を放置すると催促の連絡がくるんですけど、その内容も前向きで「いい感じにできてきてるから続報待ってます!」のような感じなんです。
特に OSS に関わる人の多くはボランティアとして活動しているだけに、モチベーションがエネルギーに繋がると思うんですけど、彼はそこのコントロールがうまいなあと思いました。さらに相手のモチベーションをなるべく下げないようにしつつ、別の要望を言ってくるんですよね。おかげで僕は既存のいけてない部分をあちこち直す羽目になったんですけど、まあそうやってうまくリソースを使って開発を継続的に進めていくということは大切だなと改めて思いました。実際のところ本人がどう思ってたのかはわからないんですけどね。
英語の話
PR を送ってコード修正するのは別に大したことではなかったんですけど、 README に説明書き足してくれって言われちゃって、まともな英語かけるかなあなんて最初はビクビクしたんですけど。結局てきとうに書いて送ったら一応意味は通じたっぽくて、 the つけろとか細かい指摘もらったのであとはもう言われるがままに整えて一応なんとかなりました。
英語が得意じゃなかったとしても、とりあえずそれっぽく書いておけば誰かが指摘するなり直してくれたりするし、やるだけやってみるとよいと思いました。
ただまあ README だけじゃなくて、 Pull Request 自体全体でコメント 80 件以上ついてるように結構なやりとりをしなければならなくて、そこにだいぶ時間をとられたなーとは思ってるので、英語力を鍛えるのは課題だなあと改めて認識しました。
まとめ
なんかさらっと終わらせるつもりだったんですけどだいぶあれこれ書いちゃいました。その労力をパーフェクト PHP 改訂版に回せって話ですね。すいませんがんばります。来年にはきっと..
さてさて、 PHP CS Fixer を活用すればコーディング規約を準拠するコストがぐっと抑えられることが伝わったらいいなーと思います。あとはまあ PSR の採用が進むといいなと。
PHP CS Fixer は使い方自体は簡単で、あとはどう設定するかだと思います。ドキュメントは1ページでだいたいまとまってるので、何かあったらドキュメントを見てみるのがよいでしょう。
最近 Go でスクリプト書いたりしてるんですけど、 Go には標準で gofmt ってのがあって細かいこと気にせずにコードかけるんで、どんな言語であれ規約に沿って自動的に直してくれるツールは積極的に導入していきましょう。
宣伝
直接は関係ないんですけど、今度 スクー でコードレビューについてお話しさせていただく予定です。日付とかまだ調整中なんですけど、決まったらまた告知するんでよかったらみてください。
追記
12/24 19:00 に決まりました!ぜひ見ていってください。
コードレビュー入門 小川 雄大 先生 - Schoo(スクー)
P.S.
そういえば PHP_CodeSniffer とかどうなってるのかなーと思って今みたら 12/5 に 2.0 がリリースされたばかりっぽくて、いまでも開発続いてるみたいなんで使いたい人は使ってみればいいんじゃないでしょうか。
Composerを使った簡単Travis CI設定
これは PHP Advent Calendar 2013 - Qiita [キータ] の5日目の記事です。
みなさんこんにちは。fivestarことクロコスの小川です。
Composerを使うと簡単に依存ライブラリを管理することが可能です。Composer とはなんぞや、という方は下記の記事あたりに目を通してみてください。
Composerを活用したモダンな開発手法をPHPカンファレンス2013で発表してきた。 #phpcon2013 | Engine Yard Blog JP
Composerでは例えば次のようにcomposer.jsonファイルを書くことで依存ライブラリを指定できます。この例だとFacebookのPHP SDKが使えるようになります。
{ "require": { "facebook/php-sdk": "dev-master" } }
Composerとオートロード
Composerを使うポイントの1つに、オートロードが自動設定される点があります。つまり、requireを書いたり、spl_autoload_register()を書いたりすることなくライブラリのクラスが呼び出せるようになる、ということです。Composerを使ってライブラリをインストールするとvendor/autoload.phpというファイルが自動的に作られるので、それを読み込むだけで外部ライブラリのオートロードが有効になります。シンプルですね。
なので、テストの際もphpunit.xmlにvendor/autoload.phpを読み込むように記述しておけば、オートロードが有効になった状態でテスト可能です。
<?xml version="1.0" encoding="UTF-8"?> <phpunit bootstrap="./vendor/autoload.php" colors="true"> <testsuites> <testsuite name="hogeee"> <directory suffix="Test.php">./Tests</directory> </testsuite> </testsuites> <filter> <whitelist> <directory>./</directory> <exclude> <directory>./vendor</directory> </exclude> </whitelist> </filter> </phpunit>
従来であれば、各ライブラリがオートロードの仕組みを独自で実装していたのですが、Composerがオートロードの仕組みも含めて管理してくれるため、利用者は1ファイル読み込めばよくなり、すごく楽になっています。
require-dev
Composerを使うと、開発時のみに読み込みたいライブラリの指定も可能です。それはcomposer.jsonにて次のように指定します。"require-dev" というのがそれです。
{ "require": { "facebook/php-sdk": "dev-master" }, "require-dev": { "phpunit/phpunit": "3.7.*", "phake/phake": "2.0.*@dev", "piece/stagehand-testrunner": "3.6.*" } }
この例だとPHPUnit、Phake、Stagehand_TestRunnerを開発時のみインストールする、という指定です。このようなテスティングツール系は運用時には基本的に不要なので、require-devに含めておくのがよいです。
なお開発時のみ、という判定はインストール時に--devオプションを指定することで行います。
% php composer.phar install --dev
(追記) --dev がデフォルトでつくようになっていたらしい。今は逆に、require-devを含めたくない場合に--no-devつけろってことでした。 @hidenorigoto @brtriver ご指摘ありがとうございます!
Composer: Installing require-dev by default
Composer: Installing require-dev by default - Jordi Boggiano
参考までに、僕が作っているCrocosSecurityBundle というライブラリは次のようにrequire、require-devを設定しています。
{ ... "require": { "php": ">=5.4.0", "symfony/framework-bundle": "2.3.*@dev", "symfony/http-foundation": "2.3.*@dev", "doctrine/common": "2.2.*" }, "require-dev": { "symfony/config": "2.3.*@dev", "symfony/dependency-injection": "2.3.*@dev", "symfony/doctrine-bridge": "2.3.*@dev", "symfony/event-dispatcher": "2.3.*@dev", "symfony/http-kernel": "2.3.*@dev", "doctrine/orm": ">=2.2.3,<2.4-dev", "facebook/php-sdk": "dev-master", "phake/phake": "2.0.*@dev" }, ... }
そもそもこのライブラリはSymfonyのバンドルっていう、まあプラグインみたいなもので、基本的にSymfonyに組み込んで使うものなので、Symfonyがあればいいんです。とはいえ開発時にはテストをする必要があります。いちいちSymfonyに組み込んでテストするのも大掛かりで煩わしいので、Symfonyの中で使っているコンポーネントをrequire-devに入れておいて、Symfonyに組み込まなくても自力で依存しているSymfonyのコンポーネントをインストールしてテストできるようにしています。
その他にも、Doctrine ORMやFacebook PHP SDKと連携する仕組みも提供していて、これは使いたい人だけ使えよっていう機能なの該当のライブラリはrequireに入れていないのですが、やはりテストは書いておきたいのでrequire-devに指定しています。
あ、ちなみにCrocosSecurityBundleはid:Yudoufuの協力もあってSymfony2.3にようやく対応しました。ゆどうふありがとう。
Travis CI
Travis CIはGitHubのリポジトリをCIするためのサービスで、ご存知の方も多いかと思います。
こういうやつです。

サービスフック設定をして、リポジトリに.travis.ymlを入れておくと、自動的にテストをしてくれるやつです。インストール方法はGetting startedをみればわかるっていうか画面をポチポチしてればほとんどやってくれちゃうのでまあやってみればよいです。

Travis CIではcomposerがプレインストールされているため、.travis.ymlに次のように書くだけで、自動的にライブラリをインストールしてPHPUnitを実行してくれるようになります。(オートロードはphpunit.xml.distで設定している前提です)
language: php
before_script:
- composer install --dev
php:
- 5.4
- 5.5
Packagist
おまけ。Packagistっていうのは、Composerでインストールできるライブラリのリポジトリです。こいつもGitHubと連携していて、GitHubにあるリポジトリを簡単に登録することができます。せっかくなので、登録方法を簡単に紹介します。
Travis CIは設定を.travis.ymlに書きましたが、Composerはcomposer.jsonにライブラリの説明などを記述します。CrocosSecurityBundleだったら下記みたいに書いています。
{ "name": "crocos/security-bundle", "description": "This bundle provides a way to configure security with annotations", "keywords": ["annotations","security","authentication","authorization"], "type": "symfony-bundle", "homepage": "https://github.com/crocos/CrocosSecurityBundle", "license": "MIT", "authors": [ { "name": "OGAWA Katsuhiro", "email": "ogawa@crocos.co.jp" } ], ... }
簡単に説明しておくと、下記のような内容を書いておきます。
- name: パッケージの名称。ベンダー名/ライブラリ名 形式
- description: 説明
- keyword: タグを配列で指定
- type: だいたい "library"
- homepage: Webサイト。なかったらGitHubのURLでいいと思います
何かいていいかわからなかったら、Composerのリポジトリブラウザで適当に同じようなやつ探してまねればいいと思います。
で、とりあえず書き終わったら次のコマンドでチェック。is validとでれば大丈夫らしいです。
% php composer.phar validate ./composer.json is valid
そこまでできたらGitHubにpushして、あとはPackagistにGitHubのリポジトリを登録します。Packagist内でそこら中にある「Submit Package
Packagist」をおして登録画面にいき、リポジトリのURLを登録します。登録したときのこと忘れたんですが、HTTPSで登録した気がします。 (https://github.com/xxx/xxx.git)
あとはcomposer.jsonを勝手にみてうまいことやってくれます。
https://packagist.org/packages/crocos/security-bundle
で、Travis CIと同様、Packagistもサービスフックを設定することで、pushするたびにPackagistの情報も自動更新されるようになります。登録したGitHubリポジトリのSettingsからService Hooksを開き、Packagistを選んでAPI Tokenの登録をします。API TokenはPackagistのマイページ(右上のユーザ名のリンク)からYour API Tokenのところにあります。

さてさて、たいした内容ではありませんでしたが今回はここまで。Composer関連はその辺のPHPライブラリのcomposer.jsonみればいろいろヒントが書いてあるので、いっぱい探してみましょう。
次は @hidenorigoto さんのMVCの記事ですね。楽しみですね。
追記:
実装の問題としてクラスの関係がどうだとか、どことどこに関連があるのが正しい/間違いだとかいうレベルのことではないのです。ソフトウェアがどういう構成になっていればよいのかを抽象的に示したものなのです。
PHPメンターズ -> Beyond MVC
期待通り、すばらしい記事でした。