PHP7 の名前空間の一覧（宣言済みの名前空間付きクラス名や定義済み関数の調べ方）

> 色々 `include` しすぎたり `auto_load` した際に、<strong>利用したいクラス名はわかるも、呼び出すと「名前空間が違う」</strong>と怒られます。

- 関連記事: 「[名前空間とは](https://qiita.com/KEINOS/items/2924ecde3e4bab0ead7e#%E5%90%8D%E5%89%8D%E7%A9%BA%E9%96%93%E3%81%A8%E3%81%AF)」| PHP の PSR-0 と PSR-4 で autoloader の違いと名前空間の基礎 @ Qiita

## TL; DR <sub><sup>（今北産業）</sup></sub>

1. **定義済みのクラスや関数の一覧を取得して、該当する名前空間を確認**しましょう。
2. [`get_declared_classes` 関数](http://php.net/manual/ja/function.get-declared-classes.php)や [`get_defined_functions` 関数](http://php.net/manual/en/function.get-defined-functions.php)を使って確認できます。
3. 以下が具体的なサンプルです。
    ```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 <sub><sup>（Phar 化したら名前空間が歪んだ）</sup></sub>

### Hello Error!

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

以下が、`Phar`化（アーカイブ）される本体 PHP スクリプトです。`index.php` と `Functions.php` の２つのファイルが `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`として実行されているか確認](https://qiita.com/KEINOS/items/e0a58abfeacfeab35be7)をするために `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](https://qiita.com/search?q=php+box+phar)」を利用しているのですが、てっきり `Box` の名前空間を使うのかと思っていたのですが、手当たり次第思いつく名前空間をつけても NG でした。

そこで、以下のように **[`get_declared_classes()`](http://php.net/manual/ja/function.get-declared-classes.php)を使って定義済みのクラスを一覧表示させた**ところ、びっくり。

```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
}
```


## 参考文献

- 「[is it possible to get list of defined namespaces](https://stackoverflow.com/questions/5225971/is-it-possible-to-get-list-of-defined-namespaces)?」 @ StackOverflow
- 「[get_declared_classes](http://nz2.php.net/manual/ja/function.get-declared-classes.php)」 @ PHP.net