[英]Can PHP __autoload() a class from within another __autoload() of the same class?
好的,這是一個艱巨的任務...我想,我感覺答案是肯定的,但在那種情況下,我希望找到一些替代方法的答案。
我在一個可以動態創建類的框架中有一個非常復雜的__autoload()函數。 為了動態創建稱為AuthActions的類,需要三個類-這三個類是:fRecordSet,RecordSet和AuthAction(請注意,該類上沒有S)。
我的自動加載器會在加載的任何類上尋找靜態方法“ init”,然后嘗試運行該方法。 在我的ActiveRecord類上,它嘗試使用AuthActions以獲得特定活動記錄上受支持的操作的列表。 AuthAction(無S)也在其init中調用AuthAction,因此基本上會加載Active Record,並嘗試加載AuthAction,觸發其他三個加載,然后在完成加載后仍將AuthAction保留在原始自動加載器中AuthAction嘗試調用AuthActions會觸發另一個自動加載,因為原始自動加載尚未完成。
這將導致以下內容,其中包含一些echo語句以供澄清:
嘗試加載ActiveRecord
嘗試加載fActiveRecord
通過/var/www/dotink.org/inkwelldemo/inc/lib/flourish加載的fActiveRecord
ActiveRecord通過/var/www/dotink.org/inkwelldemo/inc/lib加載
嘗試加載AuthAction
嘗試加載RecordSet
嘗試加載fRecordSet
通過/var/www/dotink.org/inkwelldemo/inc/lib/flourish加載的fRecordSet
通過/var/www/dotink.org/inkwelldemo/inc/lib加載的RecordSet
嘗試加載AuthAction
AuthAction通過/var/www/dotink.org/inkwelldemo/models加載致命錯誤:在第24行的/var/www/dotink.org/inkwelldemo/models/AuthAction.php中找不到類'AuthActions'
這里的問題是,對__autoload('AuthActions')的后續調用將成功,因為它現在所需的三個類已經就位了……但是似乎僅在已經嘗試自動加載'AuthActions'的前提下就死了-這似乎在PHP中是很難的。
在測試中,我發現以下內容將永遠循環,沒有錯誤:
function __autoload($class) {
__autoload($class);
}
$foo = new Bar();
盡管下面的錯誤類似地顯示:
function __autoload($class) {
$test = new Bar();
}
$foo = new Bar();
這種行為似乎不一致,因為它們本質上應該等同於同一事物(有點)。 如果PHP內部觸發的自動加載行為就像用戶對__autoload()的調用一樣,我認為我不會有問題(或者如果這樣做了,那么它將永遠循環是一個問題,這將是確定為什么類未加載以解決依賴項)。
簡而言之,我需要一種基於PHP觸發的自動加載遞歸循環自動加載器的方法……這根本不可能嗎? 我的特定版本可能有錯誤嗎? 在我的測試中,它似乎影響了5.2.6-5.3.2,所以我無法想象這是一個總體錯誤。
更新:
AuthAction上的init method()的代碼如下:
/**
* Initializes the AuthAction model
*
* @param array $config The configuration array
* @return void
*/
static public function init($config) {
// Establish permission definitions and supported actions
$every_permission = 0;
$supported_actions = array();
foreach (AuthActions::build() as $auth_action) {
$action_name = $auth_action->getName();
$action_value = intval($auth_action->getBitValue());
$every_permission = $every_permission | $action_value;
$supported_actions[] = $action_name;
define(self::makeDefinition($action_name), $action_value);
}
define('PERM_ALL', $every_permission);
}
您可以看到它在哪里調用AuthActions作為一個單獨的類,請注意,這僅僅是因為它是在最初嘗試加載失敗的情況下加載的。 我顯然可以刪除此代碼,並且可以正常工作-AuthActions的原始加載將成功完成,因為隨后將加載所有必備類。
就是說,init()是此代碼最合適的地方,即使我無法使用尚未在init()中加載的相互依賴的類,我仍然希望保留該功能。 任何實現該功能的替代方式都將非常好...理想情況下,PHP會具有此類事件,例如,當觸發“自動加載”事件時,您可以注冊一個回調。 這將允許代碼在原始自動加載之后運行,並解決此看似毫無意義的限制。
有了這樣的說法,任何關於每次加載類時如何自動調用init()的建議都將受到歡迎。
僅當嘗試使用尚未定義的類/接口時,才調用__autoload方法。
因此,以您的示例
function __autoload($class) {
$test = new Bar();
}
$foo = new Bar();
您正在嘗試加載不需要/必需的類bar
,因此未定義該類,因此它最后調用__autoload方法,然后在自動加載中再次嘗試加載未定義的同一類。
使用__autoload的正確方法將在php網站中顯示。
<?php
function __autoload($class_name) {
require_once $class_name . '.php';
}
$obj = new MyClass1();
$obj2 = new MyClass2();
?>
而且您所有的init東西都可以放在__constructor
中嗎?
除非我從您的問題中遺漏了一些東西...
我認為這
我的自動加載器會在加載的任何類上尋找靜態方法“ init”,然后嘗試運行該方法。
是解決您問題的關鍵。 您的自動裝帶器不應運行任何東西,它應包括(或以其他方式定義)該類,而沒有其他任何東西。
當定義一個類時(例如,在您的靜態“ init”方法中),您嘗試運行哪種代碼?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.