ОК, это тяжело ... Я думаю, и у меня есть чувство, что ответ просто нет, но в этом случае мне бы хотелось получить ответы на альтернативы.Может ли PHP __autoload() использовать класс из другого __autoload() того же класса?
У меня очень сложная функция __autoload() в структуре, которая может динамически создавать классы. Для динамического создания класса AuthActions необходимы три класса: эти три: fRecordSet, RecordSet и AuthAction (обратите внимание, что на этом нет S).
Мой автозагрузчик будет искать статический метод «init» для любого класса, который он загружает, и попытаться его запустить. В моем классе ActiveRecord он пытается использовать AuthActions, чтобы получить список поддерживаемых действий для определенной активной записи. AuthAction (no S) также вызывает AuthActions внутри его init, поэтому в основном загружается Active Record и пытается загрузить AuthActions, запуская загрузку остальных трех, а затем, когда он заканчивает загрузку AuthAction, все еще в исходном автозагрузчике AuthAction пытается позвонить AuthActions, который запускает еще одну автозагрузку, поскольку исходный файл еще не завершен.
Это приводит к тому, после чего имеет некоторое эхо заявления уточнить:
Attempting to load ActiveRecord
Attempting to load fActiveRecord
fActiveRecord loaded via /var/www/dotink.org/inkwelldemo/inc/lib/flourish
ActiveRecord loaded via /var/www/dotink.org/inkwelldemo/inc/lib
Attempting to load AuthActions
Attempting to load RecordSet
Attempting to load fRecordSet
fRecordSet loaded via /var/www/dotink.org/inkwelldemo/inc/lib/flourish
RecordSet loaded via /var/www/dotink.org/inkwelldemo/inc/lib
Attempting to load AuthAction
AuthAction loaded via /var/www/dotink.org/inkwelldemo/modelsFatal error: Class 'AuthActions' not found in /var/www/dotink.org/inkwelldemo/models/AuthAction.php on line 24
Проблема здесь заключается в том, что последующий вызов __autoload («AuthActions») будет преуспевать, потому что три класса он требует теперь на месте ... но, по-видимому, он умирает только от посылки, что он уже пытается автозагрузить «AuthActions» - это, кажется, hardwrit в PHP.
В тестировании этого я нашел следующий цикл навсегда без ошибок:
function __autoload($class) {
__autoload($class);
}
$foo = new Bar();
Хотя это один ниже будет ошибка аналогично:
function __autoload($class) {
$test = new Bar();
}
$foo = new Bar();
Такое поведение кажется несовместимым как по существу они должны составлять то же самое (kinda). Если PHP внутренне инициировал автозагрузку, действовал как пользовательский вызов __autoload(), я не думаю, что у меня возникла бы проблема (или если бы я сделал то, то это была бы проблема его циклизации навсегда, что было бы отдельной проблемой для определения того, почему класс не загружался для разрешения зависимостей).
Короче говоря, мне нужен способ либо рекурсивно зациклировать автозагрузчик, как на основе автозагружаемых PHP-файлов ... это просто невозможно? Возможно, это ошибка в моей конкретной версии? Кажется, это влияет на 5.2.6 - 5.3.2 в моих тестах, поэтому я не могу себе представить, что это ошибка.
Update:
Код метода 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() для класса при каждом его загрузке, приветствуются и приветствуются.
Возможно, вы захотите проверить реализации SPL для __autoload, чтобы лучше понять, как он предназначен для использования. Вы можете выполнить довольно красивую загрузку файлов, если будете следовать структуре/структуре стиля/структуре стиля Zend и пространству имен или использованию 5.3 и механике пространства имен. http://us2.php.net/manual/en/function.spl-autoload.php – tsgrasser
SPL не делает ничего, кроме создания стека автозагрузчиков из того, что я знаю. Mine делает что-то совсем другое, но независимо от того, проблема не решена автозагрузчиками SPL, так как каждый автозагрузчик будет по-прежнему обрабатываться с такой же резкой смертью при любых таких попытках загрузить тот же самый класс, который загружается в настоящий момент. – 2010-07-16 08:05:56
Могу ли я также добавить к оригинальному плакату ozatomic, примеры, которые я предоставил, - это просто показать, как поведение отличается в зависимости от того, запущена ли автозагрузка внутри, независимо от того, вызвана ли она пользователем. Это касается только моей проблемы, поскольку мне нужно, чтобы она выполнялась во второй раз. Я не просто пытаюсь загрузить тот же класс навсегда, я понимаю, что это не то, как используется автозагрузчик. – 2010-07-16 08:08:03