Porque você deve usar tratamento de  exceções em seus projetos PHP.
Tags: php, exceptions, ptbr
Published: 2021-08-02 00:44:55


### Para ter mensagens bonitas para o usuário.

É claro que mensagens bem tratadas para o usuário final da aplicação é algo importante, mas não é apenas por isso que você deveria utilizar tratamentos de exceções, e claro, melhor que só usar, é usar bem. Mas antes de irmos para o motivo, vamos entender um pouco mais sobre.

### O que são Exceções no PHP?

Exceções são como uma saída final. É como se seu código estive em um fluxo, e por algum motivo esse fluxo foi quebrado e precisa ser interrompido. Essa interrupção é chamado de exceção. 
No PHP existe uma classe Exception, que implementa uma interface Throwable. Talvez você já tenha se deparado com o seguinte trecho de código:

```php
<?php

try {
	// Something
} catch (Throwable $e) {
	echo $e->getMessage() . PHP_EOL;
}
```

Isso funciona bem quando queremos capturar qualquer tipo de erro ou exceção. E talvez ter um carinha assim no final deva ser uma boa pratica. Mas se for pra colocar esse cara em todos os lugares que queremos tratar exceções, é melhor não colocar. O real motivo de tratar exceções foi banalizado dessa maneira. Afinal de contas, agora só vai mostrar uma mensagem mais bonitinha realmente.

Mas vamos com calma, vamos entender essas palavras que foram ditas e outras mais:

- **Throwable** é uma interface que somente o próprio PHP pode implementar.
- **Error** é uma classe base do PHP de qualquer erro que pode ser emitido.
- **Exception** também é uma classe base, mas no PHP não existem exceções. Ele conta com uma biblioteca padrão chamada SPL Exceptions.
- **SPL Exceptions** fornece um conjunto de Exceptions padrões, que são dividas em exceções logicas e exceções em tempo de execução.

Não se preocupe em decorar cada uma. O que vamos utilizar e precisamos de mais atenção são as SPL Exceptions, mais especificamente a exceções em tempo de execução.

Isso não significa que as outras não são importantes, elas vão te ajudar no momento em que seu código for interpretado, se alguma exceção for jogada você terá um problema em alguma parte de seu código.

Já as exceções de tempo de execução não poderão ser "adivinhadas" pelo PHP quando seu código estiver sendo interpretado. Por isso a importância maior nesse tipo.

### Como então seria o jeito certo de usar?

Jeito certo?

Talvez não existe um jeito certo, existe o jeito que vai te ajudar a resolver problemas, e isso é especifico para cada projeto ou sistema. Mas eu vou passar algumas dicas que fui aprendendo no dia a dia de uso.

1. Não precisa usar em tudo: 

    Não precisa definir um bloco try catch em todas as funções de todas as classes do seu sistema. 

    Você pode definir apenas quando chama-las.

2. Tente ser o mais especifico possível:

    Use como parâmetro do catch exceções mais especificas, como exemplo InvalidArgumentException, que é utilizada quando um argumento é invalido.

    Ou até mesmo as suas próprias exceções criadas.

3. Utilize para tentar resolver o problema:

    Quando você define um exceção especifica, tecnicamente você sabe qual foi o erro, por isso da para tentar corrigi-lo ali mesmo.

    Crie um registro de log quando a exceção for capturada

4. Não recrie a roda:

    Utilize o máximo da exceções padrões de que o PHP oferece.

    Encontre [aqui](https://www.php.net/manual/pt_BR/spl.exceptions.php) uma lista com todas as exceções já disponíveis.

### Espera, Tem como criar minha própria Exceção?

Sim, e além de ser uma mão na roda, deixa seu código mais elegante.

Imagine uma situação onde é necessário validar se o campo tem nome e sobrenome.

```php
<?php

class NomeSemSobrenomeException extends DomainException
{
    public function __construct($campo, $nome)
    {
        $mensagem = "O campo {$campo} com valor {$nome} não contem nome e sobrenome.";
        parent::__construct($mensagem);
    }
}
```

Aqui criamos uma classe, e repare que no final do nome da classe existe um "Exception", isso não é necessário, mas pode ser um padrão legal a se seguir. 
Essa classe estende a classe DomainException. Eu costumo utilizar essa classe ao invés da Exception por se tratar de uma exceção que compete somente ao meu domínio de aplicação.
Dentro da classe eu reescrevo a função de construção para passar dois parâmetros, e personalizar uma mensagem que é passada ao construtor do seu parente, que no caso é a classe DomainException.

```php
<?php 

/**
 * @throws Exception
 */
function salvaFormulario()
{
    $inputNome = "Felipe";
    $valida = explode(" ", $inputNome);

    if (count($valida) <= 1) {
        throw new NomeSemSobrenomeException("Nome", $inputNome);
    }

    // persiste a informação...
    echo "Salvando...";
}

try {
    salvaFormulario();
} catch (NomeSemSobrenomeException $e) {
    echo $e->getMessage() . PHP_EOL;
}
```

Agora sempre que eu tenho um formulário que preciso validar se o campo nome tem o nome e sobrenome eu só preciso criar minha validação e se o valor não atender minha condição eu jogo a nova exceção personalizada. 

Repare que eu chamo a função salvaFormulario() dentro do bloco try. Se você utilizar um IDE, talvez ela te ajude nesses momentos. Quando você escreve uma função e coloca uma anotação (@throws Exception) acima da sua declaração, sempre que você chamar essa função sua IDE lhe dirá que você precisa utilizar o bloco try para chama-la.

Mas não se limite apenas a isso. Você pode criar uma função dentro da classe de exceção que registra o log, ou que tenta tratar o dados, ou até mesmo da um tipo de solução ao cliente, entre outras.

### Por que considero que criar exceções e trata-las é importante?

Erros existem em todos os sistemas, sejam eles simples ou complexos. Mas é importante que esses erros sejam encontrados e corrigidos. Por isso eu listei alguns motivos:

1. Log de erros

    Você pode pensar em alguma maneira melhor de acompanhar os erros que poder analisar e escolher qual o mais critico ou mais ocorrente? Log pode salvar seu sistema.

2. Manutenibilidade

    A facilidade de corrigir um problema quando você sabe exatamente da onde vem esse problema. Isso não tem preço.

3. Validações

    Quando eu pego um código hadouken para dar manutenção, isso me da uma tristeza, mas eu penso: "tudo bem, esse é meu trabalho". Quando você pode escrever exceções separadas, ou utilizar uma exceção especifica que vão fazer com que o fluxo e a logica do seu sistema seja obedecida, isso te eleva um nível de profissionalismo maior. 

4. Pense na sua equipe de suporte

    Quando o usuário do sistema passa aquela mensagem: "estou clicando mil vezes no botão de salvar aqui e não acontece nada", ou então: "Tentei fazer o lançamento aqui e apareceu esse erro. Segue em anexo o print do erro". E quando você abre o print tem uma mensagem do tipo: "PHP Fatal error: Uncaught RuntimeException: Index invalid or out of range in...". Bom isso me da muita dor de cabeça. 

### Boa, agora vou usar isso em tudo!

Vamos com calma meu jovem. Talvez toda essa leitura tenha te trazido ideias de como fazer uma implementação super da hora e tudo mais. 

Sim, isso é ótimo e eu te encorajo muito a não acreditar em tudo que eu disse, mas ir testar e experimentar por conta própria.

Mas eu preciso te deixar um pensamento que vem me rodeado a um bom tempo.
Existem milhões de praticas, milhões de ferramentas e tudo mais, e sempre parece que precisamos aprender mais e mais sobre tudo e usar tudo isso que vamos aprendendo. Mas é claro não entenda isso errado, quanto mais você estudar e mais souber, mais preparado para resolver os problemas você estará, então por favor, **NUNCA PARA DE ESTUDAR.**

Mas a questão é saber resolver o problema de maneira simples. Eu mesmo já cai no erro de querer colocar tudo que aprender nos cursos e livros para resolver um problema simples, mas isso me causou problemas ainda maiores depois quando eu precisei dar manutenção ou modificar algo. 
Só tome cuidado para não acabar criando problemas maiores para resolver um problema simples.