Jonathan Lamim (Convidado)
Jonathan Lamim (Convidado)

#5 PHP 7 – Error Handling, Assertions e Expectations

Compartilhe

Nesse post, falaremos sobre Error Handling no PHP 7, explicando, primeiramente, os conceitos de Assertions e Expectations.

Assertions

Desde o PHP 4 a função 'assert()' está disponível, e ela serve para adicionar ‘sanity-checks’ no código. Ela deve ser utilizada somente para desenvolvimento, nunca em ambiente de produção, e pode ser facilmente ativada e desativada usando 'assert_options()' ou 'assert.active' no php.ini.

Para usar assertions você passa uma expressão ou string como primeiro parâmetro. Veja no código abaixo um exemplo, e se a expressão ou string resultar em FALSE, será retornado um ‘warning’.


assert('$user instanceof \MyProject\User');
assert($user instanceof \MyProject\User);

O ‘warning’ que pode ser retornado é algo do tipo:


Warning: assert(): Assertion "$user instanceof \MyProject\User" failed in  on line 

Expectations

No PHP 7, o 'assert()' foi expandido para Expectations RFC, permitindo fazer chamadas a assertions zero-cost, que não geram impactos sobre o desempenho. Com essa mudança, não só é possível desativar assertions, mas também remover toda a sobrecarga completamente.

Nessa configuração, assertions não são compiladas, independente da string ou expressão passadas, portanto, geram um impacto 0 (zero) sobre o desempenho. Isso é diferente caso assertions esteja desativada, que vai resultar em expressões que ainda serão avaliadas, afetando potencialmente a execução e irá ignorar a chamada.

Veja abaixo um exemplo de ativação de assertions:


//Ativa assertions
zend.assertions  = 1
//Disativa assertions
zend.assertions  = 0
//define zero-coast assertions
zend.assertions  = -1

Conclusão

Com a adição de assertions zero-cost, você finalmente terá uma maneira leve para adicionar sanity-check ao seu código durante o desenvolvimento, sem afetar a produção. Assertions podem ser um primeiro passo no caminho para a adição de teste unitários para a sua aplicação.

Error Handling

Desde o PHP 4 que a manipulação de erros esteve inalterada, exceto pela adição de E_STRICT no PHP 5, E_RECOVERABLE_ERROR no PHP 5.2 e E_DEPRECATED no PHP 5.3.

Antes do PHP 7, se uma classe não fosse instanciada corretamente, um valor nulo ou objeto era retornado. Agora, todas as classes vão lançar uma exceção no caso de falha no instanciamento, variando o tipo e a razão da falha.


try {
    new MessageFormatter('pt_BR', null);
} catch (\IntlException $e) {

}

O fragmento de código acima vai resultar em uma \IntlException com a mensagem Contructor failed.

Engine Exceptions

Com o PHP 7, quase todos os erros fatais e capturáveis serão tratados como “engine exceptions”. Isso é possível porque uma exceção não capturada ainda resulta em um erro fatal.

Com essa mudança temos alguns benefícios:

  • Objetos __destruct() são chamados
  • Callbacks registrados com register_sutdown_function() são chamados
  • Assim como acontece com todas as exceções, haverá um rastreamento de pilha, tornando-o mais fácil a depuração

Error Exceptions

O PHP 7 traz novos tipos de “error exceptions”, cada uma com um propósito diferente. Vejamos alguns deles.

\AssertionError

Com as melhorias feitas para uso de assertions, se você informa ‘assert.exception’ como 1 no php.ini, uma exceção será lançada quando a declaração falhar.


try {
    ini_set('assert.exception', 1);
    assert('true === false', 'Assertion failed');
} catch (\AssertionError $e) {

}

O código acima vai resultar em uma exceção com a mensagem passada como segundo parâmetro para a função 'assert()', “Assertion failed”.


Se você não informar o segundo parâmetro para a função 'assert()', a exceção \AssertionError não terá nenhuma mensagem. Ainda sim será possível obter informações como a origem e a informação de que a afirmação falhou.

\TypeError

Agora que o PHP permite definir o tipo de variável e retorno de métodos e funções, estes também lançarão exceções informando sobre os erros.


function example(callable $callback)
{
   return $callback()
}

try{
  example(new stdClass);
}catch(\TypeError $e){

}

O código acima vai resultar em uma exceção com a mensagem “Argument 1 passed to example() must be callable object given, called in on line “, pois foi passado como parâmetro uma classe e não uma função.

\ArithmeticError e \DivisionByZeroError

Essas duas exceções foram adicionadas para poder lidar com cálculos aritméticos. A primeira, \ArithmeticError, será lançada sempre que ocorrer um erro ao executar operações matemáticas. A segunda, \DivisionByZeroError, é mais específica, e vai ser lançada sempre que houver uam tentativa de divisão por zero.


try{
  1 >> -1;
}catch(\ArithmeticError $e){

}

O código acima vai resultar em uma exceção com a mensagem “Bit shift by negative number”.


try{
  10 % 0
}catch(\DivisionByZeroError $e){

}

O código acima vai resultar em uma exceção com a mensagem “Modulo by zero”, pois há uma tentativa de dividir um valor por zero.

Conclusão

Essas novas exceções que vieram com o PHP 7 vão ter grande impacto na forma como você escreve o seu código, mas se você não estiver utilizando ‘set_error_handler()’, então não terá a necessidade de fazer alterações na sua aplicação para que ela continue funcionando.

PHP 7

Confira outros posts da nossa série de PHP 7:

Jonathan Lamim (Convidado)
Jonathan Lamim (Convidado)