Ограничить обработчик ошибок PHP конкретным пространством имен

Есть ли какой-либо путь в PHP для установки обработчика ошибок только для определенного пространства имен? Я создаю небольшую структуру, и мне бы хотелось попробовать все сообщения об ошибках/предупреждениях/уведомлениях внутри этого пространства имен, установив собственный обработчик ошибок и исключив из него исключения. Ошибки, вызванные вне этого конкретного пространства имен, должны вести себя обычным образом.

Можно ли это сделать с PHP?

Спасибо.

Ответ 1

Извините заранее, что на самом деле не пытайтесь это сделать до публикации:

Пятый (необязательный) параметр, который PHP передает вашему методу обработчика ошибок (и который обычно игнорируется) представляет собой массив $errcontext, который указывает на текущую таблицу символов PHP. Моя мысль заключается в том, что если вы можете извлечь пространство имен из backtrace из Exception, как было предложено Rudie, тогда также вполне возможно получить информацию о пространстве имен аналогичным образом из $errcontext. Если это правда, тогда ваш обработчик ошибок может проверить свое собственное пространство имен и "провалиться", возвращая значение false, если текущее пространство имен не соответствует тому, для которого предназначен обработчик ошибок.

Кроме того, обработчики ошибок могут быть "сложены", что означает, что, по крайней мере, в принципе (если мое предложение "my" $errcontext действительно работает), вы можете установить отдельный обработчик ошибок для каждого пространства имен.

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

Удачи!

Ответ 2

Я не пытался это сделать раньше, поэтому заранее прошу прощения, если это не сработает (по крайней мере, это может заставлять вас думать), но вот как я попытаюсь это сделать:

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

Теперь, когда у вас есть эта функция, нам нужно выяснить, как вызвать эту функцию. Поскольку все объекты в вашем пространстве имен расширяют BaseClass, все они имеют доступ к этому методу errorHandler(). Теперь внутри вашего кода вы можете использовать обычные блоки try/catch для захвата исключений, которые происходят, и вместо использования стандартной модели исключений вместо этого вы должны позвонить $this- > errorHander() (теперь, когда я думаю об этом, вы можете захотеть поставить некоторые параметры здесь - возможно, исключение вы получите из оператора catch). Это должно дать вам то, что вам нужно для частей кода, которые вы ожидаете от проблем.

Следующая часть, которую мы должны выяснить, - это обрабатывать исключения, которые вы не ожидаете, и как вы планируете маршрутизировать их через этот обработчик ошибок. Это немного сложнее, потому что это решение опирается на блок try/catch где-то. Поскольку это основа, я собираюсь предположить, что все выполняется через index.php или какой-либо другой файл начальной загрузки (что-то вроде Zend Framework или тому подобного). Если это так, то я бы поставил вашу попытку/поймать туда, где начинается обход рамки. Исходя из исключения, которое вы получаете в блоке catch, вы можете решить, хотите ли вы запустить его с помощью метода errorHandler(). Я должен администрировать эту порцию, так или иначе чувствую себя немного грязной и что должен быть лучший способ сделать это (возможно, когда вы пойдете дальше, лучшее решение представится).

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

Ответ 3

Можно ли это сделать с PHP?

Это можно сделать довольно легко, я бы сказал. Без написания кода это то, что я сделал бы:

  • Создайте блок try/catch
  • Поймать все исключения (\Exception)
  • Найти последний вызываемый класс (где-то в $exception->getTrace())
  • Этот класс будет иметь свое пространство имен в своем имени: some\name\space\Class
  • Используйте dirname($namespace) для удаления имени класса ("Class" в этом случае)
  • Делайте все, что угодно, с результатом ИЛИ сверните исключение: throw $exception;

изменить
Даже замыкания имеют пространства имен:

namespace oele\boele;

$fn = function() {
  throw new \Exception;
};

try {
  $fn();
}
catch ( \Exception $ex ) {
  print_r($ex);
}

$ex->getTrace()[0]['function'] будет oele\boele\{closure}

изменить
Слишком плохо, что массив trace не имеет ключа 'namespace' для каждого элемента.