如果您使用别名来导入命名空间类,请注意,class_exists 将无法使用简短的别名类名 - 显然,只要类名用作字符串,就只能使用完整的命名空间版本
use a\namespaced\classname as coolclass;
class_exists( 'coolclass' ) => false
(PHP 4, PHP 5, PHP 7, PHP 8)
class_exists — 检查类是否已定义
范例 #1 class_exists() 范例
<?php
// 在尝试使用类之前检查类是否存在
if (class_exists('MyClass')) {
$myclass = new MyClass();
}
?>
范例 #2 autoload
参数范例
<?php
spl_autoload_register(function ($class_name) {
include $class_name . '.php';
// 检查 include 是否声明了该类
if (!class_exists($class_name, false)) {
throw new LogicException("无法加载类: $class_name");
}
});
if (class_exists(MyClass::class)) {
$myclass = new MyClass();
}
?>
如果您使用别名来导入命名空间类,请注意,class_exists 将无法使用简短的别名类名 - 显然,只要类名用作字符串,就只能使用完整的命名空间版本
use a\namespaced\classname as coolclass;
class_exists( 'coolclass' ) => false
注意:class_exists() 只检查类!
<?php
interface DemoInterface {};
var_dump(class_exists('DemoInterface')); // false
trait DemoTrait {};
var_dump(class_exists('DemoTrait')); // false
class DemoClass {};
var_dump(class_exists('DemoClass')); // true
?>
常用函数
<?php
/**
* 检查类/特性/接口是否已定义。
*
* @param string $name 类/特性/接口的不区分大小写的名称
* @param bool $autoload 是否调用 spl_autoload()
* @return bool
*/
function structure_exists(string $name, bool $autoload = true): bool
{
return class_exists($name, $autoload)
|| interface_exists($name, $autoload)
|| trait_exists($name, $autoload);
}
?>
注意:class_exists 不区分大小写,类实例化也是一样。
php > var_dump(class_exists("DomNode"));
bool(true)
php > var_dump(class_exists("DOMNode"));
bool(true)
php > var_dump(class_exists("DOMNodE"));
bool(true)
php > $x = new DOMNOdE();
php > var_dump(get_class($x));
string(7) "DOMNode"
(在 Linux 上使用 PHP 5.5.10 测试)
这可能会导致将类名与文件名关联时出现一些问题,尤其是在区分大小写的文件系统上。
如果您在自动加载函数中递归加载多个类(或混合手动加载和自动加载),请注意,class_exists()(以及 get_declared_classes())不知道在 *当前* 自动加载调用期间先前加载的类。
显然,已声明类的内部列表只会在自动加载函数完成之后更新。
大家好!
小心,在检查 spl_autoload_register 之后是否存在类时,不要忘记第二个布尔参数 $autoload(默认值为 TRUE)。建议一个简短的示例
文件 second.php
<?php
class Second {}
?>
文件 index.php
<?php
class First
{
function first($class, $bool) {
spl_autoload_register( function($class) {
require strtolower($class) . '.php';
});
echo class_exists($class, $bool)?'Exist!!!!':'Not exist!';
}
}
new First($class = 'Second', $bool = true); //Exist!!!!
new First($class = 'Second', $bool = false); //Not exist!
?>
因为 __autoload 执行得比布尔值返回早得多,恕我直言。
[ >= PHP 5.3]
如果您要检查是否存在特定命名空间中的类,则必须传入类的完整路径
echo (class_exists("com::richardsumilang::common::MyClass")) ? "Yes" : "No";
如果您要创建一个类目录(在我的情况下是模块)...您可以这样操作
<?php
if (is_dir($this->MODULE_PATH) && $dh = opendir($this->MODULE_PATH)) {
while (($file = readdir($dh)) !== false) {
if (preg_match("/(Mod[a-zA-Z0-9]+).php/", $file, $matches)>0) {
// 包含并创建类
require_once($this->MODULE_PATH."/".$file);
$modules[] = new $matches[1]();
}
}
} else {
exit;
}
?>
//---
这里规则是所有模块都采用以下形式
ModModulename.php,并且类与文件名同名。
此代码执行后,$modules 数组将包含所有初始化的类
请注意,`\class_exists()` 对枚举返回 `true`。
<?php
enum Test: int
{
case One = 1;
case Two = 2;
}
\var_dump(\class_exists(Test::class)); // bool(true)
?>
考虑到这一点,正确检查类是否存在的方法是
<?php
function is_class_exist(string $class): bool
{
return \class_exists($class) && !\enum_exists($class);
}
?>
我在 Windows 7 上运行 PHP 5.3.4,在使用 class_exists() 自动加载类时遇到了一些困难。在我的情况下,当我检查类是否存在时,如果它不存在,class_exists 会自动抛出一个系统异常。我也在抛出我自己的异常,导致一个未捕获的异常。
<?php
/**
* 在这里设置我的包含路径
*/
$include_path = array( '/include/this/dir', '/include/this/one/too' );
set_include_path( $include_path );
spl_autoload_register();
/**
* 假设我有自己的自定义异常处理程序(MyException),让我们
* 尝试查看文件是否存在。
*/
try {
if( ! file_exists( 'myfile.php' ) ) {
throw new MyException('Doh!');
}
include( 'myfile.php' );
}
catch( MyException $e ) {
echo $e->getMessage();
}
/**
* 上面的代码要么包含 myfile.php,要么按预期抛出新的 MyException。
* 没有问题,对吧?class_exists() 应该也是这样,
* 对吧?那么...
*/
$classname = 'NonExistentClass';
try {
if( ! class_exists( $classname ) ) {
throw new MyException('Double Doh!');
}
$var = new $classname();
}
catch( MyException $e ) {
echo $e->getMessage();
}
/**
* 应该抛出一个新的 MyException 实例。但是,我却得到了
* 未捕获的 LogicException 等等,用于默认的 Exception
* 类和 MyException。我只捕获 MyException,因此我们有一个
* 未捕获的异常,导致可怕的 LogicException 错误。
*/
?>
通过注册一个不做任何事情的额外自动加载处理程序函数,我能够停止抛出额外的异常,而只抛出我自己的异常。
<?php
/**
* 在这里设置我的包含路径
*/
$include_path = array( '/include/this/dir', '/include/this/one/too' );
set_include_path( $include_path );
spl_autoload_register();
spl_autoload_register( 'myAutoLoad' ); // 添加这两行,不用担心...
function myAutoLoad() {}
/**
* 通过注册一个什么也不做的额外自定义自动加载函数
* class_exists() 仅返回布尔值,不会抛出未捕获的异常
*/
?>
我在一些搜索结果中找到了这个。我不记得页面 URL,但如果它在这里,可能就节省了我一些时间!
如果调用了 spl_autoload_register(),那么该函数会在类不存在时尝试自动加载类。
改用
<?php
in_array($class_name, get_declared_classes());
?>