Ограничить обработчик ошибок 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'
для каждого элемента.