web-dev-qa-db-ja.com

名前空間内にクラスが存在するかどうかを確認する方法は?

私はこれを持っています:

    use XXX\Driver\Driver;

...

var_dump(class_exists('Driver')); // false
        $driver = new Driver(); // prints 123123123 since I put an echo in the constructor of this class
        exit;

さて...この振る舞いは非常に非合理的です(PHPによれば存在しないクラスのオブジェクトを作成する)。指定された名前空間の下にクラスが存在するかどうかを確認する方法はありますか?

60
Taruo Gene

クラスをチェックするには、名前空間、フルパスで指定する必要があります:

namespace Foo;
class Bar
{
}

そして

var_dump(class_exists('Bar'), class_exists('\Foo\Bar')); //false, true

-つまりyou mustクラスへのフルパスを指定します。グローバルコンテキストではなく、ネームスペースで定義しました。

ただし、サンプルのように名前空間内でクラスをインポートする場合、インポートされた名前を介して名前空間なしでクラスを参照できますが、動的構造内、特にインライン文字列内でそれを行うことはできませんフォームのクラス名。たとえば、以下はすべて失敗します。

namespace Foo;
class Bar {
    public static function baz() {} 
}

use Foo\Bar;

var_dump(class_exists('Bar')); //false
var_dump(method_exists('Bar', 'baz')); //false

$ref = "Bar";
$obj = new $ref(); //fatal

等々。問題は、インポートされたエイリアスを処理する仕組みにあります。そのため、このような構成を使用する場合は、フルパスを指定する必要があります。

var_dump(class_exists('\Foo\Bar')); //true
var_dump(method_exists('\Foo\Bar', 'baz')); //true

$ref = 'Foo\Bar';
$obj = new $ref(); //ok
97
Alma Do

問題( class_exists() マニュアルページのユーザーノートで言及されているように)は、クラス名が文字列として与えられるときは常にエイリアスが考慮されないことです。これは、is_a()などのクラス名を取る他の関数にも影響します。したがって、クラス名を文字列で指定する場合は、完全な名前空間を含める必要があります(例:'\XXX\Driver\Driver''XXX\\Driver\\Driver')。

PHP 5.5では、この目的のためにclass定数が導入されました。

use XXX\Driver\Driver;
...
if (class_exists(Driver::class)) {
    ...
}
27
outis