既存のPHPを5.3の名前空間仕様に置き換えてみたときのメモ

5.2以前の命名規則の工夫と,5.3以降の名前空間

なんだかんだでPHPですねー.というわけで,今回は,自作Fwを調整してる中で得た,名前空間に関する知識をメモ.

PHP5.3から名前空間がサポートされました.それまでは,PEARをはじめとして,あらゆるライブラリ類は命名規則の工夫によって,何とかしてきたわけですが,5.3以降は名前空間を利用してライブラリを構成することができます.

ちなみに,名前空間バリバリなPHPのWebフレームワークには,Symfony2とか,Lithiumがあります.Lithiumはファイル構成とかを見た感じでは,結構好み.

5.2以前の命名規則

PHP5.2以前の世界では

ファイルパス
Ah/Foo/Bar.php
クラス名
Ah_Foo_Bar

こんな感じで,ディレクトリのセパレータがクラス名のアンダースコア( _ )として表現されて対応していました.これはこれでシンプルかつスマートなので,小〜中規模のアプリであれば必要十分な印象すら受けます.

5.3以降の名前空間

前項と同じファイルパスであっても,名前空間で定義する場合は,下記のようになります.Autoloaderでファイルパスと対応づけるなら,なんだかんだで名前空間もディレクトリ名と合わせる必要はあるとおもいます.

namespace Ah\Foo

class Bar {
     public function __construct() {
          // your business
     }
}

new Bar();

名前空間 ( namespaceの宣言 )の適用は,定数(constで定義されるもの)や,関数にも及びます.namespaceが宣言された中で定義された関数funcは, Ah\Foo\func()で呼び出されます.constされた定数HOGEは,Ah\Foo\HOGEとなります.

Autoloadには常に補完済みのクラス名が渡される

\Foo\Bar\Class って書いても,namespace Foo内でBar\Classとかいても,autoloadに渡されるクラス名は Foo\Bar\Class になってる.クラス名の書き方は,あんまり神経質にならなくてもokと.Tue Apr 26 01:33:08 via Echofon

new \Hoge\Fuga()とか,use Hogeしてnew Fuga()とか,名前空間を使い始めると使うときのクラス名の指定がバラつくわけですが,Autoloadに渡される文字列は常に一定の形式に,補完された状態になっています.どういうことかというと...

namespace Ah\Foo;
use Ah\Foo;

spl_autoload_register(function($className)
{
     echo $className;     // 下記のすべてのパターンで Ah\Foo\Bar となる
});

// 完全修飾名
new \Ah\Foo\Bar();

// 修飾名 ( useで指定されているときに使える )
new Foo\Bar();

// 非修飾名 ( namespaceとして指定されている使える )
new Bar();

常に,補完されて一定の結果が渡されるようなので,Autoloader系の実装も特に凝ったことをする必要はありませんでした.

予約語は外せ

従来のクラス名には組み込めたけど,名前空間ベースになると予約語系はぜんぶNGTue Apr 26 05:08:21 via Echofon

\Ah\Action\Abstractとか付けると,PHPに怒られてしまいます.

ということで,たとえばAh_Action_AbstractというストレートなAction抽象クラスは,Ah\Action\Baseという命名に変更されました.

上で全部,って書いてますけど全部は検証してないので漏れあるかもしれないです(汗

PhpStormのcatch節

catch ( Exception\Hoge $e ) { とか書くと,PhpStormさんに怒られる(;´-`) 完全修飾名で書くとokTue Apr 26 04:58:33 via Echofon

PHPが悪いわけではなくて,特定のIDE依存の話ですがPhpStorm EAP106.550で確認したのは,完全修飾名でないときにエラー扱いされる現象.

use Ah\Exception;

try {
     new UnDefinedClass();
} catch ( Exception\Hoge $e ) {
     echo $e->getMessage();
}

だと駄目で,

use Ah\Exception;

try {
     new UnDefinedClass();
} catch ( \Ah\Exception\Hoge $e ) {
     echo $e->getMessage();
}

ならOKという話.IDEに怒られるのも癪なので,ひとまず完全修飾名で書いています.

参考URL

上の例ではすべて先頭大文字でしたけど,ひょっとして\foo\bar\Classなカンジで,名前空間部は小文字が作法なのかしら.

まだまだ名前空間のうまい使い方を掴めていないので,認識の間違い・異論とかあったらゼヒお知らせください.