В моем проекте symfony4 я хочу генерировать собственные исключения, поэтому я создал Exception Class:
namespace App\Utils;
class ApiException extends \Exception
{
private $class;
private $function;
public function __construct(string $message, string $class, string $function, int $code = 0, \Exception $previous = null)
{
$this->class = $class;
$this->function = $function;
parent::__construct($message, $code, $previous);
}
public function __toString()
{
return $this->class.'\\'.$this->function.', Line '.$this->line.': '.$this->message;
}
}
throw new ApiException('Please select a date between 1950 and 2050', __CLASS__, __FUNCTION__);
App\\Utils\\Api\\by_year, Line 43: Please select a date between 1950 and 2050
что именно так, как я хочу, НО, я бы не хотел передавать __CLASS__
и __FUNCTION__
в моем броске исключения.
Куда мне нужно ввести эти два параметра, чтобы они всегда были доступны. Вызов его внутри исключения дает мне имя класса и имя функции класса ExceptionClass, а не класс, который его бросает?
Обычной практикой при создании исключения является включение полной трассировки, а не только класса, который ее выбросил. У класса PHP Exception
для этого есть собственный метод: getTraceAsString
, поэтому нет необходимости вручную передавать имя класса или функции. Вы можете изменить свой класс следующим образом:
class ApiException extends \Exception
{
public function __construct(string $message, int $code = 0, \Exception $previous = null)
{
parent::__construct($message, $code, $previous);
}
public function __toString()
{
return $this->getTraceAsString().': '.$this->message;
}
}
Если вы хотите показать только определенные уровни обратной трассировки, существует также метод getTrace
, который возвращает шаги в виде массива, но, на мой взгляд, полная трассировка всегда будет более полезной.
См. Полный пример в https://3v4l.org/UHI08.
Вывод почти идентичен тому, что PHP покажет вам для неперехваченного исключения.
зачем вообще возиться с конструктором? исключение backtrace все равно расскажет вам обо всем этом! Почему бы не отказаться от конструктора и вместо этого просто объединить строку сообщения?
throw new ApiException('Please select a date between 1950 and 2050 in ' . __CLASS__, '::' .__FUNCTION__);