Я работаю на PHP библиотека, который может использоваться в различных средах различными проектами PHP, и я стараюсь быть как можно более минималистичным.
В некоторых случаях я должен бросить исключения, например.
throw Exception('template has invalid tag');
Подобная ошибка не очень полезна без имени тега:
throw Exception('template has invalid tag: '.$tag);
Это было бы трудно локализовать и может привести к всевозможным проблемам с инъекцией.
ВОПРОС: Каков наилучший способ передачи дополнительных переменных с помощью Exception в PHP?
(примечание: моя библиотека выполняет построение SQL-запросов, и я бы предпочел, чтобы она была сосредоточена на задаче, а не на решении проблем с исключениями)
Интернационализация не является ответственность вашей библиотеки. Создать один или несколько Exception
занятия для вашего проекта \Exception
не рекомендуется, так как это слишком универсально), и пусть они хранят параметры в свойствах.
Пусть сообщения об ошибках, как они есть, но также передать значения в качестве аргументов конструкторам новых исключений. Предоставить добытчики для них. Сообщения об ошибках предназначены для разработчиков. Код, который использует вашу библиотеку, должен перехватывать исключения и отображать соответствующие им сообщения об ошибках. В любом случае они не должны отображать необработанное сообщение, которое вы предоставляете.
Например, вы объявляете в своей библиотеке:
class InvalidTagException extends \Exception
{
protected $tag;
public function __construct($message, $tag, $code = 0, Throwable $previous = NULL)
{
// Let the parent class initialize its members
parent::__construct($message, $code, $previous);
// Initialize own members
$this->tag = $tag;
}
public function getTag()
{
return $tag;
}
}
// Declare other Exception classes in a similar fashion, for each kind of exception you throw
class InvalidValueException extends \Exception
{
// ...
}
Приложение, которое использует вашу библиотеку:
try {
// call your library code here
} catch (InvalidTagException $e) {
// Handle in application specific way
} catch (InvalidValueException $e) {
// A different type of exception requires a different type of handling
}
Вы можете определить свой собственный класс исключений и добавить переменные в конструктор.
Например:
class AnswerException extends \Exception
{
protected $group;
public function __construct($message = "", $group = null, $code = 0, \Exception $previous = null){
$this->group = $group;
return parent::__construct($message, $code, $previous);
}
public function getGroup(){
return $this->group;
}
}
В этом случае вы можете вызвать исключение, используя следующий синтаксис:
throw new AnswerException('template has invalid tag',$tag);
Тогда позже вы можете поймать AnswerException
и использовать $exception->getGroup()
функция.
Одним из возможных решений является использование sprintf
как это:
throw new Exception(sprintf(_('template has invalid tag %s'), $tag));
где _()
ваша функция локализации.
Но это не лучшее решение, потому что оно все еще открыто для html-инъекций и становится довольно грязным, когда вам нужно передать около 5 переменных. WordPress использует такой подход локализации, насколько я видел.