如果您使用別名來導入命名空間的類別,請注意 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
介面 DemoInterface {};
var_dump(class_exists('DemoInterface')); // false
trait DemoTrait {};
var_dump(class_exists('DemoTrait')); // false
類別 DemoClass {};
var_dump(class_exists('DemoClass')); // true
?>
通用函式
<?php
/**
* 檢查類別/trait/介面是否已定義。
*
* @param string $name 類別/trait/介面的名稱(不區分大小寫)
* @param bool $autoload 是否呼叫 spl_autoload()
* @return bool
*/
函式 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
類別 Second {}
?>
檔案 index.php
<?php
類別 First
{
函式 first($class, $bool) {
spl_autoload_register( 函式($class) {
require strtolower($class) . '.php';
});
echo class_exists($class, $bool)?'存在!':'不存在!';
}
}
new First($class = 'Second', $bool = true); //存在!
new First($class = 'Second', $bool = false); //不存在!
?>
因為 __autoload 的執行比布林值返回早得多,依我拙見..
注意 `\class_exists()` 會針對列舉類型回傳 `true`。
<?php
enum Test: int
{
case One = 1;
case Two = 2;
}
\var_dump(\class_exists(Test::class)); // bool(true)
?>
考慮到這一點,檢查類別是否存在的正確方法是
<?php
函式 is_class_exist(string $class): bool
{
return \class_exists($class) && !\enum_exists($class);
}
?>
[ >= 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` 陣列將包含所有已初始化的類別。
我在 Windows 7 上執行 PHP 5.3.4,使用 `class_exists()` 自動載入類別時遇到一些困難。在我的情況下,當我檢查類別不存在時,`class_exists()` 會自動拋出系統例外。我也拋出了自己的例外,導致未捕獲的例外。
<?php
/**
* 在此設定我的 include 路徑
*/
$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('糟糕!');
}
include( 'myfile.php' );
}
catch( MyException $e ) {
echo $e->getMessage();
}
/**
* 上面的程式碼會包含 myfile.php 或擲出新的 MyException
* 如預期。沒問題吧?class_exists() 也應該一樣,
* 對吧?那麼...
*/
$classname = 'NonExistentClass';
try {
if( ! class_exists( $classname ) ) {
throw new MyException('真是糟糕!');
}
$var = new $classname();
}
catch( MyException $e ) {
echo $e->getMessage();
}
/**
* 應該要擲出一個新的 MyException 實例。但相反地,我得到一個
* 未捕捉的 LogicException 等等,這是預設 Exception
* 類別和 MyException 的錯誤。我只捕捉 MyException,所以我們有一個
* 未捕捉的例外,導致可怕的 LogicException 錯誤。
*/
?>
透過註冊一個額外的、不做任何事的自動載入處理函式,我就能夠停止擲出額外的例外,只擲出我自己的例外。
<?php
/**
* 在此設定我的 include 路徑
*/
$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() 只會回傳布林值,而不會擲出未捕捉的例外
*/
?>
在一些搜尋結果中發現了這個。我不記得頁面的網址,但如果它在這裡的話,可能會幫我省下一些時間!