わかりました、これは難しい問題です... 答えは単純にノーだと思いますが、その場合、代替案についていくつかの答えが欲しいです.
クラスを動的に作成できるフレームワークに非常に複雑な __autoload() 関数があります。AuthActions と呼ばれるクラスを動的に作成するには、fRecordSet、RecordSet、および AuthAction の 3 つのクラスが必要です (このクラスには S がないことに注意してください)。
私のオートローダーは、ロードしたクラスで静的メソッド「init」を探し、それを実行しようとします。私の ActiveRecord クラスでは、特定のアクティブ レコードでサポートされているアクションのリストを取得するために、AuthActions を使用しようとします。AuthAction (S なし) もその init 内で AuthActions を呼び出すため、基本的にアクティブ レコードが読み込まれ、AuthActions の読み込みを試み、他の 3 つの読み込みをトリガーします。その後、AuthAction の読み込みが終了すると、元のオートローダー内で AuthAction が呼び出しを試みます。元のオートロードがまだ完了していないため、別のオートロードをトリガーする AuthActions。
これにより、明確にするためにいくつかのエコーステートメントを含む以下が発生します。
ActiveRecord をロード
しようとしています fActiveRecord をロードしようとしています /var/www/dotink.org/inkwelldemo/inc/lib/flourish 経由でロードされた fActiveRecord
/var/www/dotink.org/inkwelldemo/inc/lib 経由でロードされた
ActiveRecordをロード
しようとしています AuthActions をロード
しようとしていますload RecordSet fRecordSetの読み込みを
試みています /var/www/dotink.org/inkwelldemo/inc/lib/flourish RecordSetを /var/www/dotink.org/inkwelldemo/inc/lib 経由
で 読み込みましたvar/www/dotink.org/inkwelldemo/models致命的なエラー: 24 行目の /var/www/dotink.org/inkwelldemo/models/AuthAction.php にクラス 'AuthActions' が見つかりません
ここでの問題は、 __autoload('AuthActions') への後続の呼び出しが成功することです。これは、必要な 3 つのクラスが配置されているためです...しかし、既に 'AuthActions' を自動ロードしようとしているという前提だけで死ぬようです --これは PHP にハードライトされているようです。
これをテストしたところ、以下がエラーなしで永久にループすることがわかりました。
function __autoload($class) {
__autoload($class);
}
$foo = new Bar();
以下は同様にエラーになりますが:
function __autoload($class) {
$test = new Bar();
}
$foo = new Bar();
この動作は、本質的に同じことになるはずなので、一貫性がないようです(ちょっと)。PHP が内部的にトリガーした autoload が __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() を自動的に呼び出す方法の提案は高く評価され、歓迎されます。