ちょっと何言ってるのかよくわからない。
別の名前空間のクラスを呼び出す
別の名前空間のクラスを呼び出すときは、以下のように完全修飾名で記述します。
namespace FOO;
class BAR{
public function __construct(){echo 'BAZ';}
}
namespace HOGE;
new \FOO\BAR(); // BAZ
new FOO\BAR(); // Fatal error: Uncaught Error: Class 'HOGE\FOO\BAR' not found
newの次にある名前空間の頭の\
をグローバルプレフィックス演算子と言いますが、これを入れ忘れると、Class not foundのFatal errorが発生します。
なぜなら、\
を使わない指定は名前空間\HOGE
からの相対パス、\HOGE\FOO\BAR
を表しているからで、当然そのようなクラスは存在しないためエラーになるわけです。
Linuxや<script>
タグなどのディレクトリ指定と同じように、頭に\
があるかないかで絶対パス1か相対パスを識別しているということですね。
現象
ところでちょっとこれを見てくれ。
namespace HOGE;
$class = 'FOO\BAR';
new $class; // BAZ ← ???
なんで?
さらに$classの中身は'FOO\\BAR'でも'\FOO\BAR'でも'\\FOO\\BAR'でも'\\FOO\BAR'でもどれでも動きます。
いみがわからなすぎるぞ。
どうやら変数からnewした場合、常に完全修飾名であると見做されてしまうようです。
namespace FOO;
class BAR{
public function __construct(){echo 'BAZ';}
}
$class = 'BAR';
new $class; // Fatal error: Uncaught Error: Class 'BAR' not found
$class = 'FOO\BAR';
new $class; // こちらならOK
BAR
は\FOO
からの相対パス\FOO\BAR
ではなく、絶対パス\BAR
として扱われています。
実はマニュアルの名前空間と動的言語機能という項目に、これについての記載があります。
あるのですが、
動的なクラス名、関数名あるいは定数名においては修飾名と完全修飾名に差はないので、 先頭のバックスラッシュはなくてもかまいません。
何言ってるのかわかんねえ。
原因
さて、この差の原因ですが、直接べた書きしたときはコンパイル時に名前解決が行われ、変数を経由したときは実行時に行われる、という違いのようです。
namespace FOO;
echo __NAMESPACE__; // FOO
eval('echo __NAMESPACE__'); // "" ←
evalは実行時に評価が行われますが、その時点での__NAMESPACE__
は空白になっています。
コンパイル時は名前空間に従って構文の解釈が行われます。
そして、コンパイル時に名前空間に関する情報は全て取り払われ、実行時には名前空間は無いものとして扱われます。
まあソースを読んだわけではなく現象からの推測ですが。
ソースコードリーディングは挫折した。
おまけ
名前空間内であれば、既存の組み込み関数やクラス、定数などと被る名前であっても堂々と命名できます。
わかりにくいのでやめたほうがいいですが。
namespace FOO;
function printf(){}
class stdClass{}
const PHP_VERSION = '6.0.0';
そして、何故かごく一部の定数だけ例外があります。
namespace FOO;
const NULL = 1; // Fatal error: Cannot redeclare constant NULL
NULL・TRUE・FALSE・ZEND_THREAD_SAFE・ZEND_DEBUG_BUILDの5定数だけは、名前空間内であろうとも定義することができません。
前三つはわかるとしても、後ろの二つはなんぞ?
あと言語構造などのキーワードは関数名として使えません。
namespace FOO;
function print(){} // Parse error: syntax error, unexpected print
function null(){} // こっちは使える
これに関する記載はユーザノートしか見当たらなかったんだけど、マニュアルにはどこかに記載はないのだろうか。
その他
別名前空間の変数を見たいときはどうすればいいんだっけ。
namespace FOO;
const BAR = 1;
$baz = 1;
namespace HOGE;
echo constant('\FOO\BAR'); // 1
echo \FOO\$vaz; // syntax error
-
正確にはルート相対パス ↩