アシアルブログ

アシアルの中の人が技術と想いのたけをつづるブログです

PHPの名前空間と主要フレームワークの対応について

こんにちは、小川です。

以前、「モダンPHP勉強会」でPHP 5.3から採用された名前空間について話したことがあるのですが、今日はその時の内容の中から、主要フレームワーク名前空間の対応に関するお話しについてご紹介したいと思います。

さて、皆さんPHP 5.3はお使いになりましたか?まだまだ少ないのではないかと思うのですが、PHP 5.3にはとても魅力的な新機能がたくさんあります。以前、「PHP5.3.0がついにリリース」という記事を書きましたので、PHP 5.3の新機能についてはぜひこちらをご覧ください。

PHP 5.3の新機能の中でも目玉と言っていいのが名前空間です。先に挙げたモダンPHP勉強会で、「もっと知りたい名前空間」というテーマで発表を行いました。細かい仕組みについてはプレゼンの中で解説しますので置いておくとして、早速主要フレームワークの対応などをご紹介していきたいと思います。

PHP Standards Working Group

ひとまず安心していただきたいことは、名前空間の利用に関して、きちんと標準を制定しようとがんばっている人たちがいるということです。
現在PHP Standards Working GroupというGoogleグループにて、主要フレームワークの作者たちが標準の制定のためのディスカッションをしています。

symfonyDoctrineCakePHPLithiumZend FrameworkSolarといったメジャーなフレームワークのコアデベロッパーなどなど、そうそうたるメンバーによってディスカッションされており、すなわちこの内容が主要フレームワークにも適応されると言うことになります。

現状すでに名前空間に関する規約の制定は一段落しています。Coding standard for PHP 5.3 and aboveというページに制定済みの一通りの内容が書いています。

ここでは、
名前空間
・クラス名
・例外
の3つに関する規約が制定されています。ではそれぞれご紹介していきます。


名前空間に関する規約

名前空間の形式:


<vendor>\<package_or_component>\<ClassName>


例:
 pear2\text_diff\Diff
 zend\controller\FrontController

名前空間は常に小文字+アンダースコア
・トップレベ名前空間にはベンダー名が入る
 ・ベンダー名は最短の名称(Zend Framework => zend, CakePHP => cake, symfony => symfony)
・サブ名前空間はいくつ定義してもよい
名前空間セパレータはディレクトリセパレータに相当する
名前空間中のアンダースコアに特別な意味はない

まず、名前空間は小文字とアンダースコアで定義します。現状のPEARの規約に慣れ親しんだ方や、PerlRubyなどをお使いの方には、アッパーキャメルケース(InvalidArgumentExceptionのように単語の先頭を大文字にする形式)でないことに違和感を感じるかもしれません。
これは、名前空間とクラス名を明確に分けるためだと思われます。例えば、use Foo\Bar;のようにインポートした場合、Barが名前空間なのかクラスなのかそれだけを見て判断することは難しいでしょう。名前空間を小文字にすることにより、可読性は上がると思われます。

名前空間の区切り文字(\)はディレクトリセパレータに相当しますので、例えばhttp\Requestの場合はhttpというディレクトリのRequest.phpを指す、ということになります。


◆クラス名に関する規約

・クラス名はアッパーキャメルケース
・クラス名にはアンダースコアを含めても良い
 ・クラス名中のアンダースコアはディレクトリセパレータに相当する
・インターフェースにはInterfaceサフィックスをつける
・抽象クラスにはAbstractサフィックスをつける

クラス名に関しては、現状のPEARと同様にアッパーキャメルケースで記述します。また、名前空間中のアンダースコアに特別な意味はない(ディレクトリセパレータでもなんでもない)とありますが、クラス名中のディレクトリセパレータは現状のPEARと同様にディレクトリセパレータに相当します。これは現状の命名との互換性を保つためのルールでしょう。


◆例外に関する規約

・全てのパッケージにはパッケージレベルの例外を定義する(例: pear2\text_diff\Exception)
・パッケージレベルの例外はクラスでもインターフェイスでもよい
・パッケージから投げられる例外は、SPL例外もしくはパッケージレベルの例外を継承もしくは実装した例外を使う

例外については細かく言及されていないので少し自信がないのですが、大体上記のようなルールだと思います。
とりあえずSPL例外で足りるところはSPL例外を、それ以外で必要ならばパッケージレベルの例外を、という感じでいいのではないでしょうか。


以上がPHP Standards Working Groupにて定義されている内容です。
実際に各種フレームワークの対応として、LithiumやZend Frameworkはこの規約に準拠するでしょう。Lithiumは現在独自の例外の定義はしていないようですが、名前空間の使い方などはこの通りになっています。
ただし、このルールから外れるフレームワークがあります。SymfonyとDoctrineです。この2に関しては、名前空間もアッパーキャメルケースとしています。これは、Doctrineが名前空間をアッパーキャメルケースにして開発が行われており、それがこのグループの制定前から開始されていたためではないかと思われます。それこそ名前空間のセパレータが\になる前から開発が進められていたと記憶していますので、仕方がないのかなと思います。

今後、PHP 5.3で名前空間を採用したコードを書く際は、上記の規約に沿って作っていくとよいかと思われます。
まだ名前空間になれていない方も多いと思いますが、実際に使っていくうちにすぐなれるのではないかと思います。

名前空間を使えば、長ったらしい名前を毎回タイピングする必要もなくなりますし、名前の衝突を恐れることもなくなるでしょう。
主要フレームワークPEARの次期バージョンでは名前空間を採用することになりますので、機会があればその時に色々と使ってみるとよいかと思います。