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

Вопрос

Есть ли способ заставить PHP игнорировать повторные объявления классов вместо того, чтобы сгладить FATAL ERROR?Или, по крайней мере, выдать исключение? (тогда я мог бы легко его перехватить и продолжить (а также журнал попыток автозагрузки).)

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


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

Справочная информация

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

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

Неустранимая ошибка PHP: Невозможно переопределить класс PHPUnit_Framework_Constraint в /usr/share/php/PHPUnit/Framework/Constraint.php в строке 62

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

Во-первых, я понятия не имею, чтовызывает это.Я настроил используемый загрузчик, но чередуюсь только между «Cannot redeclare» и «Could not open file», в зависимости от используемого пути включения.Здесь нет среднего уровня, то есть нет точки, где не возникает ошибка.Тем не менее, я все еще расследую.(Однако вопрос не в том, о чем вопрос.)

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

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

(Подчеркну: Я не хочу помогать с моими автозагрузчиками. Вопрос не в этом. )

Ответы [ 3 ]

8 голосов
/ 14 июля 2010

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

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

Итак, ответ на ваш вопрос: «Вы не можете».

3 голосов
/ 12 апреля 2013

Я не знаю, если вы все еще заинтересованы в ответах, но я столкнулся, возможно, с той же проблемой, с которой вы столкнулись при смешивании автозагрузки и рефлексии. Вот моя гипотеза о том, почему автозагрузка не срабатывает:

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

Мое решение: прежде чем создавать экземпляр класса отражения, я проверяю, является ли идентификатор класса полностью пространственным по имени. Если это не так, я не использую отражения. Так как некоторые классы не загружаются, вы можете решить вашу проблему.

2 голосов
/ 14 июля 2010

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...