Хорошо, это сложный вопрос ... Я думаю, и я чувствую, что ответ просто нет, но в этом случае я хотел бы получить ответы на некоторые альтернативы.
У меня есть очень сложная функция __autoload () в среде, которая может динамически создавать классы. Для динамического создания класса с именем AuthActions требуется три класса - это три: fRecordSet, RecordSet и AuthAction (обратите внимание, что на этом нет S).
Мой автозагрузчик будет искать статический метод "init" в любом загружаемом классе и попытаться запустить его. В моем классе ActiveRecord он пытается использовать AuthActions, чтобы получить список поддерживаемых действий для конкретной активной записи. AuthAction (без S) также вызывает AuthActions в своем init, поэтому в основном загружается Active Record и пытается загрузить AuthActions, инициируя загрузку остальных трех, а затем, когда он заканчивает загрузку AuthAction, все еще в исходном автозагрузчике, AuthAction пытается вызвать AuthActions, которая запускает другую автозагрузку, так как оригинальная еще не завершена.
Это приводит к разъяснению следующего, в котором есть некоторые эхо-операторы:
Попытка загрузить ActiveRecord
Попытка загрузить fActiveRecord
fActiveRecord загружается через /var/www/dotink.org/inkwelldemo/inc/lib/flourish
ActiveRecord загружается через /var/www/dotink.org/inkwelldemo/inc/lib
Попытка загрузки AuthActions
Попытка загрузить RecordSet
Попытка загрузить fRecordSet
fRecordSet загружается через /var/www/dotink.org/inkwelldemo/inc/lib/flourish
Набор записей загружается через /var/www/dotink.org/inkwelldemo/inc/lib
Попытка загрузить AuthAction
AuthAction загружается через /var/www/dotink.org/inkwelldemo/models
Неустранимая ошибка: класс 'AuthActions' не найден в /var/www/dotink.org/inkwelldemo/models/AuthAction.php в строке 24
Проблема здесь в том, что последующий вызов __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 в моих тестах, поэтому я не могу представить, что это общая ошибка.
Обновление:
Код для метода init () в AuthAction приведен ниже:
/**
* 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 () для класса при каждой его загрузке.