Подтвердить что ты не робот

PHP превращает "вызов функции-члена в не-объект" в исключение

Когда я выполняю шаги "Behat", обработчик ошибок Behat превращает ошибки "Попытка получить свойство неъектных" в исключения.

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

Однако ошибки "Вызов функции-члена на не-объекте" являются фатальными и немедленно останавливают выполнение теста (в том числе прерывание записи результатов в xml). Это бесполезно.

Мои вопросы:

  • В чем разница между этими двумя ошибками? Различаются ли они "уровни ошибок"? Где это документировано? Я искал сайт PHP и Google и не могу найти каноническую ссылку, просто много вопросов об отладке конкретных экземпляров каждой ошибки.

  • Есть ли способ конвертировать последнюю ошибку в исключение, а не полностью останавливать script? Мне не кажется, что разыменование "null" с "->" было бы ошибкой, из-за которой "невозможно восстановить, например, проблему с распределением памяти".

Update:

Похоже, что это только известная проблема с PHP. См:

  • # 51882 Вызов функции-члена для не-объекта должен исключать исключение
  • # 46601 E_RECOVERABLE_ERROR для "Вызов функции-члена на не-объекте"
  • # 51848 Ошибки вызова необъектных методов должны быть увлекательными с помощью set_error_handler()
  • # 63538 "Вызов функции undefined" должен быть увлекательным

Некоторые люди говорят это "по дизайну", но я думаю, что это просто артефакт уровней ошибок, которые были определены до того, как объекты были добавлены в PHP. В языке, отличном от OO, вызов несуществующей функции является серьезной ошибкой, и я могу видеть, как это может быть описано как "фатальное" или "не восстанавливаемое" (хотя на языке, отличном от OO, где функции могут быть определены на летят, даже это кажется чересчур пессимистичным). В наши дни, когда вы можете сделать "$a->f()" на любом старом $a, гораздо более вероятно, что "f" может не существовать, и похоже, что это не должно быть фатальной ошибкой (см. Java где это будет исключение NullPointerException).

Я полагаю, это приводит меня к новому вопросу:

_ 3. Как вы могли бы напасть на PHP, чтобы сделать ошибки "Вызов функции-члена на не-объекте" нефатальными, без массово нарушающейся обратной совместимости, и какие шаги вы могли бы предпринять, чтобы максимизировать вероятность того, что этот патч будет принят в PHP?

Обновление 2 re patching PHP:

Для этого исправления существует некоторая ограниченная поддержка в списке рассылки внутри PHP. Теперь мне просто нужно написать патч, чтобы исправить это и создать RFC.

4b9b3361

Ответ 2

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

Отметьте этот код для некоторого простого вывода с номерами ошибок.

Теперь внимательно посмотрите на часть "Устанавливать и вводить неустановленное свойство". Вы можете видеть, что PHP дает вам сообщение "Создание объекта по умолчанию из пустого значения". Поэтому, если класс не существует, PHP создаст его для вас. То же самое происходит, когда вы используете typecasting, см. типность объектов

Таким образом, вы можете получить доступ к не-объекту, потому что он проверяет эту propety в динамическом созданном объекте по умолчанию. Но если вы обращаетесь к методу, этот объект по умолчанию все еще не имеет этого метода.

Вот почему свойство возвращает ошибку уровня 8, а метод - ошибку уровня 1 (см. уровни ошибок). И поскольку он возвращает фатальную ошибку уровня 1, вы не сможете продолжить работу после этого процесса.

Ответ 3

У меня есть хорошие новости для вас: есть библиотека PHP, доступная под названием Исключения ошибок, которая превращает все ошибки PHP в захватывающие исключения.

Это довольно драматическое изменение в том, как все работает, но ясно, что вы не единственный, кто хотел это сделать.

The lib написан Энтони Феррарой, который является одним из основных разработчиков PHP, поэтому вы можете быть уверены, что он знает, что он делает, но если вы хотите сделать это самостоятельно, он подключается к PHP с помощью set_error_handler() function; если вы хотите уловить ошибки PHP, вот как вы это делаете.

Надеюсь, что это поможет.