Автозагрузка PHP: Предотвращение 'не может повторно объявить <класс>' во всех совокупностях?

Вопрос

Существует ли способ, которым я могу заставить PHP проигнорировать переобъявления классов, а не блевать ФАТАЛЬНАЯ ОШИБКА? Или, по крайней мере, выдайте исключение? (Я мог легко поймать его затем и продолжить двигаться (также журнал предпринятая автозагрузка).)

Я предполагаю не, и фатальная ошибка является фатальной ошибкой - в конце концов, в девяносто девять из ста случаев, это - довольно разумное поведение - и я должен буду, вероятно, просто зафиксировать экземпляры его инициированный в зависимости от конкретного случая. Но возможно кому-то более умному, чем я выяснили это.


Если бы Вы спрашиваете себя, "С какой стати Вы хотели бы сделать это?", продолжать читать.

Фон

Я работаю над инструментом, который использует Отражение для агрегации определенной информации об используемых функциях и классах. Одним из аргументов сценария является дополнительный файл начальной загрузки для создания Отражения более надежным с автозагрузкой (меньше ReflectionExceptions это заканчивается пойманное и инициирование эвристики нейтрализации, потому что классы неизвестны в определенном файле).

Теперь, загружающиеся загрузки, которые прекрасный автопогрузчик (автопогрузчики), и сценарий выполняет, как предназначено, перемещения через несколько сотен файлов без жалобы, пока я не наткнулся на препятствие:

Фатальная ошибка PHP: не Может повторно объявить класс PHPUnit_Framework_Constraint в/usr/share/php/PHPUnit/Framework/Constraint.php на строке 62

У меня есть две проблемы:

Один, я понятия не имею, что инициировало это. Я скорректировал начальную загрузку, которая используется, но только чередуется между, 'Не может повторно объявить', и 'Не удалось открыть файл', в зависимости от включать используемого пути. Нет никакого второго плана, т.е. никакого смысла, где никакая ошибка не происходит. Однако, я все еще занимаюсь расследованиями. (Эта проблема не то, что вопрос о, все же.)

Два, что еще более важно, и ведущий к предмету этого вопроса, мне нужен способ поймать его. Я попытался писать пользовательский обработчик ошибок, но это, кажется, не хочет работать на Fatal errors (несколько разумно, можно было бы спорить).

Я намереваюсь выпустить этот инструмент в мир с открытым исходным кодом в какой-то момент, и это кажется мне довольно недопустимым поведением. У меня есть эвристика нейтрализации для классов, которые не существуют - я быть бы они объявляться однажды слишком редко, чем слишком часто, но не злоупотребляя эвристику, также, который должен сказать, я действительно хочу предложить возможность использования bootstrapper. Не повреждая сценарий. Когда-либо. Даже если это - худший автопогрузчик в истории автопогрузчиков.

(Для выделения: Я не хочу справку со своими автопогрузчиками. Это не то, о чем этот вопрос.)

10
задан pinkgothic 14 July 2010 в 13:51
поделиться

2 ответа

Одним из лучших вариантов избежать Cannot redeclare является функция class_exists. Вы можете использовать ее в автозагрузке для предотвращения повторного объявления классов. С помощью class_exists вы не обязаны ловить ошибку, вы просто предотвращаете ее.

На самом деле существует два вида фатальных ошибок: улавливаемые и не улавливаемые. Повторное объявление класса не вызывает E_RECOVERABLE_ERROR (ошибка, которую можно поймать), и вы не можете ее обработать.

Итак, ответ на ваш вопрос: "Нельзя."

.
8
ответ дан 3 December 2019 в 23:48
поделиться

Автозагрузка никогда не будет автоматически пытаться загрузить уже загруженный класс. Если у вас есть класс >1 с таким же именем, вы, вероятно, делаете это неправильно.

Если вы анализируете «небезопасный» код, вы можете поискать в файле имя класса, прежде чем пытаться загрузить его, но это следует использовать только в крайнем случае, так как это огромная трата процессора и, вероятно, просто скрытие допустимых ошибок.

Если у вас есть структура требования и система автозагрузки, вы можете включить файл один раз в автозагрузку, а затем снова в требование. Вы можете взломать исправление, обернув класс с помощью if( class_exists( ) { ... <классовая декларация здесь> ... }

2
ответ дан 3 December 2019 в 23:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: