У меня есть это:
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 не существуют). Есть ли способ проверить, существует ли класс в данном пространстве имен?
Чтобы проверить класс, вы должны указать его с пространством имен, полным путем:
namespace Foo; class Bar { }
а также
var_dump(class_exists('Bar'), class_exists('\\Foo\\Bar')); //false, true
-если вы должны указать полный путь к классу. Вы определили его в своем пространстве имен, а не в глобальном контексте.
Однако, если вы импортируете класс в пространстве имен, как в своем примере, вы можете ссылаться на него через импортированное имя и без пространства имен, но это не позволяет делать это в динамических конструкциях и, в частности, в строковых строках, которые формирует имя класса. Например, все следующие не будут выполнены:
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
Проблема (как упоминается в class_exists()
странице руководства пользователя class_exists()
) заключается в том, что псевдонимы не учитываются, когда имя класса указывается в виде строки. Это также влияет на другие функции, которые принимают имя класса, например is_a()
. Следовательно, если вы укажете имя класса в строке, вы должны указать полное пространство имен (например, '\XXX\Driver\Driver'
, 'XXX\\Driver\\Driver'
).
PHP 5.5 вводил константу class
только для этой цели:
use XXX\Driver\Driver; ... if (class_exists(Driver::class)) { ... }