如何检查命名空间中是否存在类?

2022-08-30 08:26:48

我有这个:

    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不存在的类的对象)。有没有办法检查给定命名空间下是否存在类?


答案 1

为了检查类,你必须用命名空间,完整路径指定它:

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

答案 2

问题(如class_exists()手册页用户说明中所述)是,每当以字符串形式给出类名时,都不会考虑别名。这也会影响采用类名的其他函数,例如 。因此,如果在字符串中给出类名,则必须包含完整的命名空间(例如 , )。is_a()'\XXX\Driver\Driver''XXX\\Driver\\Driver'

PHP 5.5 引入了这个常量就是为了这个目的:class

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

推荐