PHP
BOX
namespace
get_declared_classes

PHP の名前空間の一覧(調べ方)

TL;DR

色々 include しすぎたり auto_load した際に、利用したいクラス名はわかるも、呼び出すと名前空間が違うと怒られる場合は 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

Hello Error!

ちょっとしたアプリを作成したので、配布する際に単一の実行可能な PHP ファイルとして配布できるように Phar 形式(PHPアーカイブ)でアーカイブしました。

以下が、Phar化(アーカイブ)される本体 PHP スクリプトです。

index.phpFunctions.php の2つのファイルが HelloWorld.phar としてアーカイブされ、$ php HelloWorld.phar を実行すると「Hello World.」と表示するだけのシンプルなものです。

index.php
<?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;
}
Functions.php
<?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クラスが見つからないんっすけど?:angry:」と怒られています。

自分のスクリプト内では Phar クラスの定義はしていないため、当然といえば当然のエラーです。

A Class With No Name Space ~ 名前空間のないクラス ~

では、問題の Phar クラスはどこに属しているのか。

私は、Phar アーカイブを行う際に便利なアーカイバー「Box」を利用しているのですが、てっきり Box の名前空間を使うのかと思っていたのですが、手当たり次第思いつく名前空間をつけても NG でした。

そこで、get_declared_classes()を使って定義済みのクラスを一覧表示させたところ、びっくり。

index.php
<?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 クラスの前にバックスラッシュ(\)を加えてエラーを回避しましたとさ。トホホぃのほい。

Functions.php
<?php

namespace KEINOS\Sample;

function is_phar()
{
    return strlen(\Phar::running()) > 0 ? true : false; // Phar -> \Phar
}

参考文献