Symfony勉強会で酔った勢いでPSRのステマをLT枠でしてきたのですが、参加者の半数以上がPSRを知っているというSymfony勉強会のレベルの高さに完全にやる気を失い、気のない話しかできなかったことをまずはお詫び申し上げます。
アレだとちょっと何が言いたかったのか意味不明ですので、改めて解説したいと思います。スライドはもう上げなくていいか。。
PSRとは
PSRとはPHP-FIGっていう、色々なフレームワーク原作者同士の集まりみたいなところで策定されている「コーディング規約」です。標準だの何だの書いてありますが、要はコーディング規約ですよ。
ずっと公式サイトが無くてググラビリティが低いなクソッと思っていたら、いつの間にか公式サイトができていたようです。これで安心して「PSR公式サイトはここだよ!」と案内できますね
レベル分けがあって、今はPSR-0, PSR-1, PSR-2の3つが公開されています(これ以上増えていく可能性ももちろんあります)。PSR-1は0を必ず守れ(MUST)と書いてあるし、PSR-2は1を必ず守れ(MUST)となっているので、例えばPSR-2準拠ならPSR-1,PSR-0共に準拠、という意味になります。
- PSR-0 - Autoloading Standard (クラス名とオートローディングに関する標準)
- PSR-1 - Basic Coding Standard (基本コーディング標準)
- PSR-2 - Coding Style Guide (コーディングスタイルガイド)
最後がStandardでなくGuideになってて何となく弱気な印象を受けますが、数字が小さいほうが重要だという認識で合ってると思います。
んで、一番重要なPSR-0は、クラス名とオートローダーの規約なわけです。hnwさんが日本語訳されていたので詳しくはそちらも見るといいと思います。
- 名前空間とクラスの完全な名前として、次のような構造を持たせてください。 \<ベンダー名>\(<名前空間>\)*<クラス名>
- どの名前空間も、トップレベルの名前空間として「ベンダー名」を持つ必要があります。
- どの名前空間も、第二レベル以下については好きなように使うことができます。
PSR-0 を和訳してみた - hnwの日記
トップレベルに必ず「ベンダー名」をつけろ、というところがポイントです。
問)以下のコードの問題点を述べよ
PSR-0に従ってないと何が起きるか考えてみます。以下のコードはPSR-0に従っていません。何が問題でしょうか?
<?php class User { }
何の問題もないように見えますが、、PHPだとこのコードは非常にまずいのです。
PHPはグローバルクラス、グローバル関数しかない
「User」という名前のクラスを作ると、それ以降「User」というクラスを作りなおすことはできなくなります。これは、あるパッケージ内の一時的に使いたいクラスなども全て該当します。上記コードはUserという名前を殺しているからまずいのです。
PHP5.3から名前空間がつきましたが、あれは単に長い名前に別名、エイリアスを張れる機能でしかありません。グローバルクラス、グローバル関数を作っていることに変わりはないのです。
(例えばnode.jsならファイルごとにスコープが切り離されており、「このファイル内だけでしか呼び出せない、外からは存在すら見えない関数、クラス」を作ることができます。)
グローバル空間しかないため、PHPにおいて名前は有限な資源です。資源は無闇に浪費せず、ケチケチ節約して使わないと問題が起きます。
ブラウザサイドのJavaScriptでは「ライブラリが消費するグローバル変数は一個に抑えろ」という鉄則がありますが、あれと同じです。prototype.jsとjQueryが両方とも「$」というグローバル変数を作ろうとするから大変面倒とか、まさしくそれです。
「User」「View」「Model」「Controller」といった一般名詞をクラス名として採用すると、同じ名前が二度と付けられなくなります。そのため、フレームワーク中のコードはベンダー名(Zend, Silex, Symfonyなどなど)を先頭につけて、「Acme\User」「Acme\View」「Acme\Model」「Acme\Controller」などのようにすることが必須となるのです。
PSR-0が0なのは、これがPHPの仕様であり、この規約を徹底しないといつか名前が重なって相互運用できなくなってしまうからです。
PSR-0の適用範囲はどこまでか
もともとPSR-0はフレームワークの相互運用のために作られたので、フレームワーク自体のコードに適用されるのは勿論です。
それだけでなく、フレームワークに基づいて作成するWebアプリ本体の方も、PSR-0に従った書き方をするほうが望ましいはずです。というわけで、Symfony2やZendFramework2など、アプリ本体のコードもPSR-0を強要する/自然と実施できるフレームワークが増えてきているように思います。
昔のフレームワークは「Model_」から始まる名前でないと動かないとか、「Bootstrap」という名前でクラスを作らないと動かないとか、そもそもフレームワーク自身がPSR-0を破ることを強制するものが多々あります。こういうフレームワークは、今後廃れていくような気がしています。