色々
include
しすぎたりauto_load
した際に、利用したいクラス名はわかるも、呼び出すと「名前空間が違う」と怒られます。
- 関連記事: 「名前空間とは」| PHP の PSR-0 と PSR-4 で autoloader の違いと名前空間の基礎 @ Qiita
TL; DR (今北産業)
- 定義済みのクラスや関数の一覧を取得して、該当する名前空間を確認しましょう。
-
get_declared_classes
関数やget_defined_functions
関数を使って確認できます。 - 以下が具体的なサンプルです。
sample.php
<?php namespace KEINOS\Sample; include('vendor/autoload.php'); include('Functions.php'); include('Classes.php'); print_r(get_declared_classes()); //宣言済みクラス一覧 print_r(get_defined_functions()); //定義済み関数一覧 /* ... */
TS; DR (Phar 化したら名前空間が歪んだ)
Hello Error!
ちょっとしたアプリを作成したので、配布する際に単一の実行可能な PHP ファイルとして配布できるように Phar
形式(PHPアーカイブ)でアーカイブしました。
以下が、Phar
化(アーカイブ)される本体 PHP スクリプトです。index.php
と Functions.php
の2つのファイルが HelloWorld.phar
としてアーカイブされ、$ php HelloWorld.phar
を実行すると「Hello World.」と表示するだけのシンプルなものです。
<?php
namespace KEINOS\Sample;
include('Functions.php');
if (is_phar()) {
echo 'Hello World.' . PHP_EOL;
} else {
echo 'Running directly. Not a phar file.' . PHP_EOL;
}
<?php
namespace KEINOS\Sample;
function is_phar()
{
return strlen(Phar::running()) > 0 ? true : false;
}
実行時にアーカイブ状態であるかの確認、つまりアプリ自身が Phar
として実行されているか確認をするために is_phar
ユーザ関数内で、Phar
クラスのメソッドを呼び出しています。
しかし、アプリの本体内部で namespace
(名前空間)を使っているため、次のエラーが発生しました。
$ php HelloWorld.phar
PHP Fatal error: Uncaught Error: Class 'KEINOS\Sample\Phar' not found in phar:///PATH/TO/YOUR/SAMPLE/PHAR/APP/HelloWorld.phar/src/Functions.php:7
問題のある Functions.php:7
行目というと return strlen(Phar::running()) > 0 ? true : false;
です。ここで「Phar
クラスが見つからないんっすけど? 」と怒られています。
Phar
クラスは自分のスクリプト内では定義はしていないため、当然といえば当然のエラーです。
A Class With No Name Space ~ 名前空間のないクラス ~
では、問題の Phar
クラスはどこに属しているのか。
私は、Phar
アーカイブを行う際に便利なアーカイバー「Box」を利用しているのですが、てっきり Box
の名前空間を使うのかと思っていたのですが、手当たり次第思いつく名前空間をつけても NG でした。
そこで、以下のように get_declared_classes()
を使って定義済みのクラスを一覧表示させたところ、びっくり。
<?php
namespace KEINOS\Sample;
include('Functions.php');
print_r(get_declared_classes());
/*
if (is_phar()) {
echo 'Hello World.' . PHP_EOL;
} else {
echo 'Running directly. Not a phar file.' . PHP_EOL;
}
*/
でるわでるわ、たかがこんなプログラムなのに、こんなに裏で定義されていたのか、と。
何がビックリしたかって、そもそも Phar
は PHP のコアなクラスであるため名前空間を持っていないことに一番ビックリでした。
まぁ、落ち着いて考えれば、そりゃそうです。
名前空間のないクラスの呼び出し方
最終的には、スクリプトを以下のように Phar
クラスの前にバックスラッシュ(\
)を加えてエラーを回避しましたとさ。トホホぃのほい。
<?php
namespace KEINOS\Sample;
function is_phar()
{
return strlen(\Phar::running()) > 0 ? true : false; // Phar -> \Phar
}
参考文献
- 「is it possible to get list of defined namespaces?」 @ StackOverflow
- 「get_declared_classes」 @ PHP.net