Подтвердить что ты не робот

Как проверить, существует ли класс в пространстве имен?

У меня есть это:

    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 не существуют). Есть ли способ проверить, существует ли класс в данном пространстве имен?

4b9b3361

Ответ 1

Чтобы проверить класс, вы должны указать его с пространством имен, полный путь:

namespace Foo;
class Bar
{
}

и

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

-i.e. должен указать полный путь к классу. Вы определили его в своем пространстве имен, а не в глобальном контексте.

Однако, если вы импортируете класс в пространство имен, как в своем примере, вы можете ссылаться на него через импортированное имя и без пространства имен, но это не позволяет вам делать это в динамических конструкциях и, в частности, Строковые строки, которые формируют имя класса. Например, все следующие не будут выполнены:

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

Ответ 2

Проблема (как указано в примечаниях пользователя class_exists()) заключается в том, что псевдонимы не учитываются всякий раз, когда имя класса указывается в виде строки, Это также влияет на другие функции, которые принимают имя класса, например is_a(). Следовательно, если вы укажете имя класса в строке, вы должны включить полное пространство имен (например, '\XXX\Driver\Driver', 'XXX\\Driver\\Driver').

PHP 5.5 ввел константу class только для этой цели:

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