Ограничить обработчик ошибок PHP определенным пространством имен - PullRequest
10 голосов
/ 21 апреля 2011

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

Можно ли это сделать с помощью PHP?

Спасибо.

Ответы [ 3 ]

2 голосов
/ 02 мая 2011

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

Пятый (необязательный) параметр, который PHP передает вашему методу-обработчику ошибок (и который обычно игнорируется), представляет собой массив $ errcontext, который указывает натекущая таблица символов PHP.Я думаю, что если вы можете извлечь пространство имен из обратного следа Исключения, как это было предложено Руди, то вполне возможно также извлечь информацию о пространстве имен аналогичным образом из $ errcontext.Если это так, тогда ваш обработчик ошибок может проверить свое собственное пространство имен и «провалиться», возвращая false, если текущее пространство имен не совпадает с тем, для которого предназначен обработчик ошибок.

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

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

Удачи!

1 голос
/ 01 мая 2011

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

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

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

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

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

0 голосов
/ 21 апреля 2011

Можно ли это сделать с помощью PHP?

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

  1. Создать блок try / catch
  2. Поймать все исключения (\Exception)
  3. Найти последний вызванный класс (где-то в $exception->getTrace())
  4. У этого класса будет свое пространство имен: some\name\space\Class
  5. Используйте dirname($namespace) для удаления имени класса (в данном случае "Class")
  6. Делайте все что угодно с результатом ИЛИ сбросьте исключение: 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' для каждого элемента.

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