Capítulo 20. Exceções

Índice
Herdando Exceções

PHP 5 tem um modelo de exceção similar ao de outras linguagens de programação. Uma exceção pode ser disparada (thrown), tentada (try) ou pega (caught) no PHP. Um bloco Try deve incluir ao menos um bloco catch. Vários blocos catch podem ser usados para pegar diferentes tipos de exceções; a execução continuará depois do último bloco catch definido na sequência. Exceções podem ser disparadas de dentro de blocos catch.

Quando uma exceção é disparada, o código que segue a instrução não será executado e o PHP tentará achar o primeiro bloco catch que bate com o tipo de exceção. Se uma exceção não for pega, acontecerá um Erro Fatal do PHP com uma mensagem de Uncaught Exception, ao menos que tenha sido definido um tratador com set_exception_handler().

Exemplo 20-1. Disparando uma Exceção

<?php
try
{
  
$error = 'Sempre dispara esse erro';
  
throw new Exception($error);

  
// Código que segue uma exceção não é executado
  
echo 'Nunca é executado';
}
catch (Exception $e) {
  echo
"Exceção pega: ",  $e, "\n";
}

/* continua execução */
?>

Herdando 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 20-2. A classe nativa Exception

<?php
class Exception {

  
protected $message = 'Unknown exception'; // Mensagem da exceção
  
protected $code = 0;                      // Código da exceção definido pelo usuário
  
protected $file;                          // Arquivo gerador da exceção
  
protected $line;                          // Linha geradora da exceção

  
function __construct(string $message=NULL, int code=0);

  
final function getMessage();              // Mensagem da exceção
  
final function getCode();                 // Código da exceção
  
final function getFile();                 // Arquivo gerador
  
final function getTrace();                // um array com o backtrace()
  
final function getTraceAsString();        // String formatada do trace

  /* Sobrecarregável */
  
function _toString();                     // String formatada para ser mostrada
   
}
?>

Se uma classe herda da classe Exception e redefine o construtor, é altamente recomendado que o mesmo chame parent::__construct() para garantir que todas as informações disponíveis sejam devidamente atribuídas. O método __toString() pode ser sobrecarregado para permitir uma saída personalizada quando o objeto é apresentado como string.

Exemplo 20-3. Herdando a classe Exception

<?php

class MyException extends Exception {

  
/* Redefine a exceção para que a mensagem não seja opcional */
  
public function __construct($message, $code = 0) {

    
// coisas personalizadas que você queira fazer
    // ...
    
    /* Garante que tudo é atribuído corretamente */
    
parent::__construct($message, $code);
  }

  
/* Representação do objeto personalizada no formato string */
  
public function __toString() {
    return
__CLASS__ . ": [{$this->code}]: {$this->message}\n";
  }

  
public function customFunction() {
    echo
"Uma função personalizada para esse 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:
        
// dispara exceção personalizada
        
throw new MyException('1 é um parâmetro inválido', 5);
        break;

      case
self::THROW_DEFAULT:
        
// dispara a padrão
        
throw new Exception('2 não é permitido como parâmetro', 6);

        break;

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

    }

  }

}

// Exemplo 1
try {
  
$o = new TestException(TestException::THROW_CUSTOM);
}
catch (MyException $e) {            /* Será pega */
  
echo "Pegou minha exceção\n", $e;
  
$e->customFunction();
}
catch (Exception $e) {              /* Ignorado */
  
echo "Pegou Exceção Padrão\n", $e;
}
var_dump($o);                       /* continua execução */
echo "\n\n";


// Exemplo 2
try {
  
$o = new TestException(TestException::THROW_DEFAULT);
}
catch (MyException $e) {            /* Tipos não batem */
  
echo "Pegou minha exceção\n", $e;
  
$e->customFunction();
}
catch (Exception $e) {              /* Será pega */
  
echo "Pegou Exceção Padrão\n", $e;
}
var_dump($o);                       /* continua execução */
echo "\n\n";


// Exemplo 3
try {
  
$o = new TestException(TestException::THROW_CUSTOM);
}
catch (Exception $e) {              /* Será pega */
  
echo "Default Exception caught\n", $e;
}
var_dump($o);                       /* continua execução */
echo "\n\n";


// Exemplo 4
try {
  
$o = new TestException();
}
catch (Exception $e) {              /* Ignorada, nenhuma exceção */
  
echo "Default Exception caught\n", $e;
}
var_dump($o);                       /* continua execução */
echo "\n\n";