我有这个:
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不存在的类的对象)。有没有办法检查给定名称空间下是否存在类?
答案 0 :(得分:89)
为了检查类,必须使用命名空间,完整路径指定它:
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
答案 1 :(得分:25)
问题(如class_exists()
手册页用户注释中所述)是,只要以字符串形式给出类名,就不会考虑别名。这也会影响其他带有类名的函数,例如is_a()
。因此,如果您在字符串中提供类名,则必须包含完整的命名空间(例如'\XXX\Driver\Driver'
,'XXX\\Driver\\Driver'
)。
PHP 5.5为此目的引入了class
常量:
use XXX\Driver\Driver;
...
if (class_exists(Driver::class)) {
...
}