PHP CS Fixer v2 でもっと快適PHPライフ

2014年に書いた PHP CS Fixer の記事 が今でも読まれているのですが、2016年末にリリースされた PHP CS Fixer v2.0後方互換のない変更が多く入っており情報が古くなっているため、改めて v2 について書いてみようと思います。なお現時点での最新版は v2.1.2 となります。

fivestar.hatenablog.com

PHP CS Fixer とは

PHP CS FixerPHP コードをコーディング規約 (CS = Coding Standards) に沿って補正してくれるライブラリです。歴史を辿ると、元々は Symfony のプロジェクトリードの fabpot 氏が作成したもので、 PSR-½ 、あるいは Symfony のコーディング規約 に沿ってコードを補正する機能が実装されています。

github.com

チームでコードを書くときはコーディング規約に沿って書くのが大前提ですが、例えばコードレビューをするときにいちいちコーディング規約の指摘をするのも不毛ですし、かといってメンバーが全員 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 という扱いで分けられるようになりました。PHPUnitphpunit.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 だけだとどういう挙動になるのか判断つかないものもあって、 テストケース を確認しながら設定していったので、この辺はもうちょっと充実していると助かりますね。

(追記)

describe コマンドなるものを教えていただきました。実行結果イメージを確認できるのでとてもわかりやすいですね。

f:id:Fivestar:20170330235135p:plain

(追記おわり)

せっかくなのでいくつかのルールをピックアップして紹介してみます。

ちなみにルールを適用した場合に手元のコードがどうなるのか確認したい時は、 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_arrowalign_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_importsuse 文のソートを行うルールです。 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 + 個別ルールで設定・リスキーな補正はしない・言わなくてもやるようなルールであっても設定する、というポリシーで用意したため、チームの環境や文化に合わせて活用するとよいでしょう。

gist.github.com

エンジニアになって10年が経ちました

エンジニアになって早10年。この10年間のふりかえりと、思いをつづりました。

年表

ふりかえり

情報処理系の道に進むまで

高校時代に趣味でオンラインゲームの情報サイトを運営しており、 HTML や CSS を調べるのが当時の趣味でした。 Firefox と出会ってから IE がおかしいことを知り、どのブラウザでも正しく表示されるよう HTML と CSS の理解を深めたいと、詳解HTML&XHTML&CSS辞典を擦り切れるほど読んでいた覚えがあります。

元々親の家業を継ぐつもりでいたものの不況の折で経営状態が芳しくなく、親から将来は好きなことをしてよいと伝えられ、漠然とパソコンを使った仕事がしたいと考え担任に相談して勧められたのが情報処理系の専門学校。調べているうちに見つけたのが日本電子専門学校に新設される「オープンソースシステム科」でした。当時はソフトウェアとハードウェアの違いすらわからないレベルでしたが Firefox を通じてオープンソースという言葉は知っており、 Firefox への謎の憧れを抱いていたこともあってここに進むことを決意します。

日本電子ではC 言語・Linunx・データベース・ネットワークといった今日の基礎を学びました。プログラミングを学ぶことは非常に楽しく技術書なども意欲的に読み漁っていたものの、これを仕事としていくイメージが湧かず、早く現場につきたいと考えていた頃、転機となったのは1年次の秋に学生スタッフとして参加したオープンソースカンファレンス(OSC)でした。

余談ですが OSC の懇親会で Mozilla Japan の中野氏と話す機会があり、「成長しなくなったら終わり」と言われたことが今日のモチベーションの支えになっています。

アシアルでのアルバイ

OSC で日本 PHP ユーザ会のブースにいたのがアシアルで、アルバイトの募集をしていると聞いてすぐに応募しました。面接時、当時アシアルの CTO だった森川穣の目の前でコードを書かされ、大したものは書けなかったものの無事に受かり、12月から働き始めることに。当時19歳でした。

入社初日に書いたコードがバグってて無限ループを引き起こしサーバを止める失態をおかしましたが、ゆどうふこと亀本大地がさらっと直してくれて、ゆどうふはいいやつだって思いました。

森川穣から年末年始の課題として超・極める! PHP を渡され、上鍵さんが書いた日本語メールの記事を読んで理解してこいと言われたものの、まったく理解できずに憂鬱だったことは今でも覚えています。

師匠との出会い

師と仰ぐ久保敦啓氏に「基礎が大切」と訓えられたのが、アシアル主催のイベントの懇親会でのことでした。その後あるプロジェクトで Piece Framework を採用することになり、久保さんから直接指導を仰ぎ、フレームワークというものについて学びます。正直にいって Piece Framework は難しかったですが、軟弱なフレームワークから始まらなかったことで調べる力が身についたかなと思います。

久保さんからは今でも様々なことを学んでおり、まさしく師匠として尊敬しています。

アシアルでの失態と反省

専門2年次にPHPプロ内の通販サイトの改修を任されたものの、 SQL のミスですべての注文データを上書きしてしまいます。社長の田中正裕がデータを復旧してくれ事なきを得ましたが、とにかく血の気が引きました。ただ、元々ロジックが整理されていないコードだったため、そこに問題があるだろうと内心反発しており、コードのあり方そのものを考えるよいきっかけでした。無論反省はしています。

勉強会への参加、登壇

そうこうしているうちに専門を卒業し、そのままアシアルに入社しました。その頃からゆどうふに誘われて PHP 勉強会に参加するようになります。調べてみたら最初に参加したのが第32回PHP勉強会でした。sotarokこと柄沢聡太郎とかいう同世代のやつが発表しててすげーなと思いつつ、負けてらんねーというライバル心がふつふつと湧いてきました。

はじめて登壇したのは第二回symfony勉強会でした。fivestar という ID を名乗り始めたものこの頃ですね。由来ですが、最初に挙げたゲームの情報サイトの名前に用いてたもので、当時好きだった WWE のスーパースター、ロブ・ヴァン・ダムのフィニッシュムーブからとったものです。

symfony を学ぶ

2008年ごろから仕事で symfony を使うようになり、MVC だなんだと学ぶようになりました。社内でも symfony をより効率的に使えるようなプラグインの開発やドキュメンテーションなどを任され、コードの共通化や再利用といったことに執心していた時期でした。後から考えればひどいものを作ったとは思いますが、効率的な開発を意識するようになったことで自身の方向性を見出していった時期でもありました。

パーフェクト PHP の執筆

執筆のきっかけは楽天テクノロジーカンファレンス 2008の出張 PHP 勉強会終了後、グリー CTO の藤本氏に声をかけられたことでした。技術評論社からパーフェクトシリーズの PHP 版を作りたいと話が来ているそうで、僕を含め5人ほど参加の意思を表明し、そこからパーフェクト PHP 執筆プロジェクトが開始しました。当時はどう考えても経験不足でしたが、若さゆえというやつです。

章立てを決めるにあたり、フレームワークのソースを読んで学んだことが大きいとの意見が多数挙がったため、フレームワークを絡めた章を用意することになったのですが、関心の高い分野だったため自分が引き受けることに。

フレームワークといっても、使い方だけ知るのではなく内部まで知ってこそと考えフレームワークを自作することにしましたが、とにかく大変でした。あらゆる知識が人に解説できるようなほど身についておらず、夜な夜な調べながら、あるいはゆどうふに教えを請いながら執筆していた記憶があります。

とにかくこの本を執筆する過程で、自分自身が大きく成長できました。そして、二度と執筆したくないと思いました。

nequal へ参加、クロコスの立ち上げ

PHP カンファレンス 2009 で sotarok とゆどうふと話していた時に、ゆどうふから「なんで nequal に入っていないの」と言われ、お互い「それもそうか」みたいなノリで nequal に参加しました。当時の僕は「誘ってきやがれ」と暗に声がかかるのを待っていたので、ようやく成就した瞬間でした。

wozozo が作っていた reroom を元に nequal としてビジネスをできないかという話になり、小澤隆生氏にエンジニア向けのビジネス勉強会を開いてもらったのが2010年の12月25日のこと。その後ランチを食べてる際、小澤さんから一緒に Facebook を活用したビジネスをやらないかと誘われ、翌年の2月7日にクロコスを創立。

アシアルを離れることは当時まったく考えていませんでしたが、 Web 2.0 の時のような新しい流れに乗りたいという思いと、 nequal のメンバーで仕事をしてみたいという思いで、4月からクロコスに移ることに。

クロコス時代

sotarok や riaf はエンジニアとして芯を持っており、彼らから学ぶことは多かったです。当初は気に食わないことも多々ありましたが、やつらの行動力や考え方はリスペクトに値するものでした。プログラミングは手段であると言うことを学んだのも彼らからです。

クロコスに入ってから半年くらい経ったころ、 wozozo とチームを組み、僕がリーダーを務めることになりましたが、当時の wozozo は割とアレなコードを書いていたので、まあ随分あーだこーだと言い続けました。当時は疎まれていたと思いますが、後に wozozo が別の会社に行った時、クロコス時代に僕が色々言ったことを今度はwozozoがチームメンバーに言う側になったと聞かされた時、言い続けたことは伝わっていたのだと感動したものです。

yuchimiri もあのメンバーの中でよくやっていました。同じチームになったのはヤフーに買収されてからですが、タフなやつだなあと思います。エンジニアとして突き抜けた存在ではなくとも、英語を学んで海外に行くなどすごいバイタリティを持ったすごいやつです。

効率的な Web アプリケーションの作り方の執筆

アシアルの終盤、実はコードを書くことにおいてスランプに陥っていました。よいコードを書きたいと思っていても、納得のいくコードが書けませんでした。ちょうどそんな時期に出てきたのが Symfony 2 で、それを通じて設計の基礎を改めて学び、徐々にコードの書き方というものを掴んでいきました。

そんな思いから書くことになったのが効率的な Web アプリケーションの作り方で、パーフェクト PHP 執筆時の苦悩を押し殺して、単独で執筆することに。無事に出版されたからよかったものの、1人で書くと言うのは本当につらかったです。

この本は Symfony を使ったため Symfony の技術書のように捉えられることがあり、そこは失敗したなと言う思いです。パーフェクト PHP の改訂版で新しいフレームワークを書き起こすため、それをベースにこの本もリプレースしたい気持ちはありますが、精神的余力から行って実現はしないと思います。

クロコスがヤフーに買収される

クロコスを立ち上げて約1年半、当時はわけがわかりませんでしたがヤフーに買収されました。そこでようやく株式と言う仕組みが少しだけ理解できました。

買収後も事業は継続し、この頃からマネジメントへの関心が高まってきます。設計も徐々に洗練されてきたと感じる時期で、自分自身の成長にも手応えを感じ始めました。

ヤフーに吸収合併

買収されてから約2年後の2014年9月、Facebook規約改定で事業が継続できなくなり、ヤフーに吸収合併されることになりました。同時に2年のロックアップ期間が解け転職ができるようになりましたが、ヤフーという大企業の中で自分がどれだけやれるかを知りたいと思いしばらくヤフーに残ることを決意。

ヤフー側の計らいもあり、体制はあまり変わらず新しい部署が作られたため、ここではチームビルディングに注力していました。この期間は高いパフォーマンスが出せていたと思いますし、ヤフー内でもおそらくトップクラスの評価を得られたため、それなりに自信にはなりました。

TRILL チームとの融合

2015年の4月から TRILL の開発チームと融合し、メディアの開発に携わるようになります。 TRILL の開発メンバーは若いエンジニアが中心で、同じチームメンバーとして相談に乗ることが増え、シニアなエンジニアだらけだったクロコスと違い新鮮でした。10月にヤフーを辞めるまでのわずかな間でしたが、よい関係を築くことができ、マネジメント方面も踏まえた自身の方向性に手応えを感じていました。

同時にカンパニー内の技術戦略室にも身を置き社内の技術体制作りであるとか、経営陣と相談の上会社全体の技術文化改善といったこともさせてもらい、貴重な経験を積めたと思います。

こうした動きをもっとやりたいと思う反面、自分のキャリアとして経営側の知識や経験が不足していると考え、自らが中心となってチームが作れるような組織への転職を希望しました。

そして Ancar へ

sotarok の紹介で Ancar と出会ったのが2015年の10月末でした。当時 Ancar は立ち上げて1年弱のスタートアップで、エンジニアがおらず、自分としてはうってつけだと思い、だいぶ勢いで転職しました。スタートアップということもあり、20代のうちにもう1度挑戦を、という思いもありました。

これまでエンジニア中心の組織にいた自分にとって、エンジニアのいない組織の文化の違いは思っていた以上に大きく、自分の力不足を踏みしめる日々です。とはいえ資金調達やらといったスタートアップの経営者ならではの課題に直面するなど新しい知見として得られるものも多く、ここから CTO としての新しい自分を構築して行くんだ、という思いで日々歩んでいます。

ちなみに Ancar はPHP エンジニア・ iOS/Android エンジニアを募集していますので興味がある方はぜひ声をかけてください。

www.wantedly.com

出会いに支えられた10年間

10年間で様々な体験をしました。よき仲間との出会いが積み重なって今の自分があることを改めて実感します。

森川穣は未だに憧れの存在で、森川さんから得たものを伝えていくことが自分の人生の目標です。そして久保師匠からの訓えに恥じない働きをしていきます。ゆどうふやsotarokといった友人たちは今でも支えになってもらっており、これからもよき付き合いが続けられることを願っています。

これから先、まずは Ancar で結果を出すことが最大の課題です。真に自らの力で切り開くべき課題として、自分自身が成長しなければ達成できません。

これまで自分のやりたい道を歩んできました。もちろん今度もやりたいことをやっていきたいと思っていますが、それだけじゃなくて恩返しができるような、得たものを世の中に還元できるような働き方をしていきたいと思っています。

来年でいよいよ30歳です。まだ20代かと言われますが、十分若手の域は超えました。10年後どうなっているかわかりませんが、いつまでも成長し続けられるよう、心していきたいと思います。

Ancarに入社しました

あけましておめでとうございます。転職すると立て続けに扁桃炎になる呪いにかかっており、この年末年始も40度を超える熱を出してずっと寝てました。健康の大切さを定期的に思い知らされます。

転職しました

先日の PHP BLT #1 でも言いましたけど12月から Ancar で働いてます。転職先を聞かれて「アンカー」って答えると Anker にいくのかと真剣に勘違いされるケースもあったりしますが、 Anker 製品愛用していて Anker も大好きですのでいつか Ancar × Anker なコラボでもできたらいいなとか妄想してます。

Ancar は自動車の個人間売買のプラットフォーム(サービス名も Ancar)を開発しているスタートアップ企業です。僕自身が自動車業界に興味を持っていることに加え、コードを書く技術以外にも経営やチームづくりなどエンジニアとしての幅を広げられる環境に身を置きたいと考えていたところに友人経由で話が来て転職が決まりました。

エンジニアは1人だけ

僕が入るまでは正規のエンジニアが1人もいない状況でオフショアやインターンらにより開発が進められており、内部事情も中々に大変なことになっていたのですが、課題が沢山あるということはそれだけ解決すれば成長できるだけのチャンスがあるし、そもそもまだ憂うような規模でもないのでいいタイミングで入ったのではないでしょうか。

ちなみにインターンでがんばってくれてた方が正式に入社することが決まっていて、早速エンジニアが2人になるのでとてもうれしいです。

エンジニア募集中

とはいえエンジニア足りないので一緒にやってくれる方募集中です。特に iOS / Android エンジニアは今いない状況なので喉から手が出るほど募集してます。

自動車産業に革命を!技術で世界に挑むエンジニア募集! - 株式会社Ancarの求人 - Wantedly

僕はどんなサービスを開発していようと常に技術力で勝負できるプロフェッショナルなエンジニアでありたいと思ってますし、一緒に上を目指し続けられるようなメンバーと共に仕事ができればうれしいなと思ってます。

ヤフーのこと

2014年10月にクロコスがなくなってヤフー社員になり、その後ヤフーで色々やらせてもらったんですけど、僕はヤフーのこと好きだしまたいつか戻りたいなって本気で思ってます。

ヤフーは今大きく変わろうとしていて、特にエンジニアが今まで以上に気持ちよく働けるようにあれこれしている最中でした。僕も自分ができる範囲で活動してきたのですが、まだまだ今のままだとできる範囲が狭く実力不足を痛感し、また1から自分のスキルを再構築しようと転職に踏み切った次第です。

がんばります

Ancar はまだまだ軌道に乗るところまで行けてなくて毎日必死にやっております。自分自身も未熟な点がまだまだあって日々勉強です。応援よろしくお願いします。

ちなみに売り玉がまだまだ足りないので車売りたい方はぜひお声をおかけください。

ancar.jp

フレームワークの先へ / PHPカンファレンス関西2015で発表してきました

PHP カンファレンス関西 2015 に参加してきました。記憶が正しければ PHP カンファレンス関西は初参加なのですが、各セッションの中身が濃く、関西のコミュニティの方々の熱い思いがひしひしと伝わってきて、勉強にもなりましたし刺激も得られたので参加して本当によかったです。

conference.kphpug.jp

僕はフレームワークトラックで Symfony のセッションを担当させてもらったのですが、 Symfony の話ではなく「フレームワークだけではなく本質に目を向けよう」という内容になっています。


終わった後、多くの方に「よかった」と言っていただいて、うれしいとかではなくホッとしました。師匠も来られてたので、こんな話を肴のあてに終わったあとお話しさせてもらいまして、また色々なことを勉強させていただきました。

一部でエモいなどと言われてますが、思いの丈をぶつけられたのでスッキリしています。

実践ドメイン駆動設計

実践ドメイン駆動設計

ちなみにスライドの中でも紹介した「実践ドメイン駆動設計」、書店ブースで完売しててビビりました。とてもよい傾向にありますね。

書店といえば、登壇直後にサイン会をさせていただく予定が、登壇中の様々なプレッシャーにより終わった後そのまま無意識に LT を見に行ってしまい、開始が遅くなって申し訳ありませんでした。

余談ですがサインを待っていただいてた方がぼくと同姓だそうで「私も小川なんです」といわれたので「ぼくは高橋って呼ばれてます」っていったら 「(何言ってんだこいつ...)」 みたいな目で見られたのであまり余計なことは言わないようにしようと思います。

Symfony 2.7.0 released (Symfony Blog)

ついでに書いておくと Symfony 2.7 がでましたね。2.3 以来の LTS バージョンで 05/2018 までメンテナンスが行われるとのことです。PSR-7 対応Asset コンポーネントの追加Twigプロファイラの追加などが行われています。PSR-7 への対応は早かったというか、それにあわせたんでしょうけど、 Symfony の内部構造が拡張可能な形で設計されているからこそ環境の変化に柔軟に対応できるわけなんですね。

5月はスクーでオブジェクト指向の講義もやったりしてだいぶ登壇する機会が多かったのですが、ようやくこれで一段落。なのでこれから PSR-7 のあたりをしっかり勉強していこうかなと思ってます。セッション聞いてくださった方や支援してくれたカンファレンススタッフの皆さまありがとうございました。

今日の19:00からスクーでコードレビュー入門の授業をします

19時より生放送です。スクーにアカウント登録すれば無料で生放送見られますので、ぜひ登録して観ていってください。クリスマスプレゼントってことでひとつよろしくお願いします。

コードレビュー入門 小川 雄大 先生 - 無料動画学習|schoo(スクー)

PHP CS Fixerで快適PHPライフ

2017/03/30 追記

新しいバージョン (v2.0) の記事を書きましたのでこちらもご覧ください

fivestar.hatenablog.com


この記事は 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-0PSR-1PSR-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-fixerfix コマンドを実行すると対象に修正が行われます。 --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 から bracesvisibility を除いた項目のみ実行したいといった場合、項目名の先頭に - をつけて指定します

% 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 がリリースされたばかりっぽくて、いまでも開発続いてるみたいなんで使いたい人は使ってみればいいんじゃないでしょうか。

OS X YosemiteのJapaneseIMでバックスラッシュを入力する

OS X Yosemite の JapaneseIM の仕様で、バックスラッシュ(\)がデフォルトで円マーク(¥)を入力するように設定されているので備忘録を残しておきます。エンジニア(特にPHPer)的には困った変更ですね。

f:id:Fivestar:20141021012835p:plain

f:id:Fivestar:20141021012829p:plain