## Estendendo exceções

Uma classe de exceção definida pelo usuário pode ser criada herdando a classe Exception. Os membros e propriedades abaixo mostram o que é acessível a partir da classe filha que deriva da Exception.

Exemplo #1 A classe nativa Exception

    <?php
    class Exception implements Throwable
    {
        protected $message = 'Unknown exception';   // Mensagem da exceção
        private   $string;                          // Cache __toString
        protected $code = 0;                        // Código definido pelo usuário
        protected $file;                            // Nome do arquivo onde a exceção originou
        protected $line;                            // Número da linha onde a exceção originou
        private   $trace;                           // Backtrace
        private   $previous;                        // Exceção anterior (se exceção empilhada)

        public function __construct($message = '', $code = 0, ?Throwable $previous = null);

        final private function __clone();           // Inibe a clonagem de exceções

        final public  function getMessage();        // Mensagem da exceção
        final public  function getCode();           // Código definido pelo usuário
        final public  function getFile();           // Nome do arquivo onde a exceção originou
        final public  function getLine();           // Número da linha onde a exceção originou
        final public  function getTrace();          // Um array do backtrace()
        final public  function getPrevious();       // Exceção anterior
        final public  function getTraceAsString();  // Backtrace formatado como string

        // Pode ser sobrescrito
        public function __toString();               // String formatada da exceção
    }

Se uma classe estender a classe Exception e redefinir o construtor, então é altamente recomendável que também seja chamado o parent::__construct() para garantir que todos os dados estejam corretamente informados. O método __toString() pode ser sobrescrito para fornecer uma representação customizada do objeto quando utilizado como string.

> Nota:

> Exceções não podem ser clonadas. Tentativas de clonar um Exception resultarão em erros `E_ERROR` fatais.

Exemplo #2 Estendendo a classe Exception

    <?php
    /**
     * Define uma classe de exceção
     */
    class MyException extends Exception
    {
        // Redefine a exceção de forma que a mensagem não seja opcional
        public function __construct($message, $code = 0, ?Throwable $previous = null) {
            // código

            // garante que tudo está corretamente inicializado
            parent::__construct($message, $code, $previous);
        }

        // Personaliza a apresentação do objeto como string
        public function __toString() {
            return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
        }

        public function customFunction() {
            echo "Uma função específica desse tipo de exceção\n";
        }
    }

    /**
     * Cria uma classe para testar a exceção
     */
    class TestException
    {
        public $var;

        const THROW_NONE    = 0;
        const THROW_CUSTOM  = 1;
        const THROW_DEFAULT = 2;

        function __construct($avalue = self::THROW_NONE) {

            switch ($avalue) {
                case self::THROW_CUSTOM:
                    // lança a exceção customizada
                    throw new MyException('1 é um parâmetro inválido', 5);
                    break;

                case self::THROW_DEFAULT:
                    // throw default one.
                    throw new Exception('2 não é um parâmetro permitido', 6);
                    break;

                default:
                    // Sem exceção, o objeto será criado
                    $this->var = $avalue;
                    break;
            }
        }
    }

    echo "# Exemplo 1\n";
    try {
        $o = new TestException(TestException::THROW_CUSTOM);
    } catch (MyException $e) {      // Entrará aqui ...
        echo "Pegou MyException\n", $e;
        $e->customFunction();
    } catch (Exception $e) {        // ... mas não aqui.
        echo "Pegou Exception padrão\n", $e;
    }

    // A execução continua
    var_dump($o); // Null

    echo "\n\n# Exemplo 2\n";
    try {
        $o = new TestException(TestException::THROW_DEFAULT);
    } catch (MyException $e) {      // Não entrará aqui ...
        echo "Pegou MyException\n", $e;
        $e->customFunction();
    } catch (Exception $e) {        // ... porque entrará aqui.
        echo "Pegou Exception padrão\n", $e;
    }

    // A execução continua
    var_dump($o); // Null

    echo "\n\n# Exemplo 3\n";
    try {
        $o = new TestException(TestException::THROW_CUSTOM);
    } catch (Exception $e) {        // Entrará aqui
        echo "Pegou exceção padrão\n", $e;
    }

    // A execução continua
    var_dump($o); // Null

    echo "\n\n# Exemplo 4\n";
    try {
        $o = new TestException();
    } catch (Exception $e) {        // Não entrará, sem exceção
        echo "Pegou Exception padrão\n", $e;
    }

    // A execução continua
    var_dump($o); // TestException

`↑` and `↓` to navigate • `Enter` to select • `Esc` to close • `/` to open