(16) 981791110 contato@policast.studio

80 passos para implementação de tratamento de erros personalizado em projetos Symfony

O Symfony é um dos frameworks PHP mais utilizados para desenvolvimento de aplicações web e possui diversas funcionalidades para tratar erros de forma nativa. No entanto, em alguns casos, pode ser necessário implementar um tratamento de erros personalizado para melhorar a experiência do usuário e/ou para lidar com situações específicas.

Neste artigo, vamos apresentar um passo a passo com 80 etapas para implementação de tratamento de erros personalizado em projetos Symfony. Este guia considera a versão 5.3 do framework e acredita que o leitor possui conhecimentos básicos em PHP e Symfony.

1. Qual a diferença entre tratamento de erros nativo e personalizado?

O tratamento de erros nativo é aquele que já vem implementado no Symfony e que é executado automaticamente sempre que um erro é gerado na aplicação. Este tratamento pode ser personalizado através da configuração de parâmetros e serviços específicos.

Já o tratamento de erros personalizado é aquele que é implementado de forma específica pelo desenvolvedor, levando em consideração as necessidades da aplicação. Este tipo de tratamento pode incluir a exibição de mensagens de erro customizadas, envio de email para o administrador da aplicação e/ou a apresentação de páginas de erro customizadas.

2. Por que implementar um tratamento de erros personalizado em projetos Symfony?

Existem diversas razões para implementar um tratamento de erros personalizado em projetos Symfony, tais como:

  • Apresentação de mensagens de erro mais claras e amigáveis;
  • Notificação imediata do administrador da aplicação em casos críticos;
  • Redução do tempo de solução de problemas;
  • Melhoria na experiência do usuário;
  • Aumento da segurança da aplicação.

3. Como configurar o tratamento de erros nativo em projetos Symfony?

O tratamento de erros nativo pode ser configurado em projetos Symfony através do arquivo config/packages/framework.yaml. Neste arquivo, é possível definir diversas opções relacionadas ao tratamento de erros, tais como o nível de detalhamento das informações de erro e a exibição de mensagens de debug.


# config/packages/framework.yaml

framework:
error_handler:
enabled: true
level: dev
debug: false
throw_at: -1
format: html
log:
enabled: true
severity: error
channels: ["!event", "!doctrine"]
handler_id: null
force_registration: false

Neste exemplo, o tratamento de erros nativo está ativado (enabled: true) e configurado para exibir informações de debug somente em ambiente de desenvolvimento (level: dev). Além disso, as mensagens de erro são exibidas em formato HTML (format: html) e são registradas no sistema de logs com gravidade “error” (severity: error).

4. Como implementar um tratamento de erros personalizado em projetos Symfony?

O tratamento de erros personalizado em projetos Symfony pode ser implementado de diversas formas, dependendo das necessidades da aplicação. A seguir, apresentamos um passo a passo com 80 etapas que podem ser seguidas para implementação de um tratamento de erros personalizado em projetos Symfony.

Passo 1 – Criação da classe de tratamento de erros personalizada

Crie uma classe de tratamento de erros personalizada que implemente a interface SymfonyComponentErrorHandlerErrorErrorHandlerInterface. Esta classe será responsável por lidar com os erros que ocorrerem na aplicação e pode ser configurada no arquivo config/services.yaml:


# config/services.yaml

services:
AppEventListenerCustomErrorHandler:
arguments: []

Neste exemplo, estamos configurando o serviço “CustomErrorHandler”, que representa a classe de tratamento de erros personalizada “AppEventListenerCustomErrorHandler”. Note que, neste caso, não estamos passando argumentos para o construtor da classe (arguments: []).

Passo 2 – Configuração do ambiente de produção para exibição de páginas de erro customizadas

Se a aplicação estiver em ambiente de produção e você desejar exibir páginas de erro customizadas, certifique-se de que as seguintes opções estejam configuradas no arquivo config/packages/prod/twig.yaml:


# config/packages/prod/twig.yaml

twig:
exception_controller: AppControllerExceptionController::showException
debug: false

No exemplo acima, estamos configurando o controller “AppControllerExceptionController::showException” para lidar com as páginas de erro. Este controller pode ser personalizado de acordo com as necessidades da aplicação.

Passo 3 – Configuração do ambiente de desenvolvimento para exibição de informações de debug

Se a aplicação estiver em ambiente de desenvolvimento e você desejar exibir informações de debug nos erros, certifique-se de que a opção “debug” esteja configurada como true no arquivo config/packages/dev/twig.yaml:


# config/packages/dev/twig.yaml

twig:
debug: true

Passo 4 – Criação das páginas de erro personalizadas (apenas se necessário)

Se você desejar exibir páginas de erro personalizadas, crie as páginas de erro desejadas no diretório “/templates/bundles/TwigBundle/Exception/” de acordo com o código de status HTTP desejado (por exemplo, “404.html.twig” para erros 404).

Passo 5 – Configuração do arquivo config/packages/security.yaml para envio de emails de notificação em casos críticos

Caso você deseje receber notificações por email em casos críticos (por exemplo, erros 500), configure o arquivo config/packages/security.yaml de acordo com as necessidades da aplicação. O exemplo abaixo mostra uma possível configuração:


# config/packages/security.yaml

security:
firewalls:
main:
anonymous: true

access_control:
- { path: ^/admin, roles: ROLE_ADMIN }

providers:
in_memory:
memory:
users:
admin:
password: admin
roles: 'ROLE_ADMIN'

encoders:
SymfonyComponentSecurityCoreUserUser: plaintext

role_hierarchy:
ROLE_ADMIN: ROLE_USER

# Configuração de envio de emails em casos críticos
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false

main:
anonymous: ~
http_basic:
realm: "Secured Demo Area"

# Configuração do listener para envio de emails em casos críticos
custom_security_listener:
user_provider: in_memory
email_sender: sender@mail.com
email_recipient: recipient@mail.com
channels: ["email"]
logout:
path: /logout
target: /login

access_control:
- { path: '^/login', roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin, roles: ROLE_ADMIN }
- { path: ^/api, roles: IS_AUTHENTICATED_FULLY }

No exemplo acima, estamos configurando um listener de segurança (custom_security_listener) para envio de emails em casos críticos. Este listener deve ser criado seguindo as orientações do passo 6.

Passo 6 – Criação do listener de envio de emails em casos críticos

Crie uma classe de listener que implemente a interface SymfonyComponentEventDispatcherEventSubscriberInterface. Esta classe será responsável por enviar emails de notificação em casos críticos e pode ser configurada no arquivo config/services.yaml:


# config/services.yaml

services:
AppEventListenerCustomSecurityListener:
arguments: ['%mailer%', '@translator.default', '%email_sender%', '%email_recipient%', '%channels%']
tags:
- { name: kernel.event_listener, event: kernel.exception, method: onKernelException }

Neste exemplo, estamos configurando o serviço “CustomSecurityListener”, que representa a classe de listener de envio de emails em casos críticos “AppEventListenerCustomSecurityListener”. Os argumentos passados para o construtor da classe são, respectivamente, o componente de envio de emails (mailer), o componente de tradução (translator.default), o endereço de email do remetente (email_sender), o endereço de email do destinatário (email_recipient) e os canais em que o listener deve ser executado (channels).

Passo 7 – Criação do arquivo .env.local para configurações específicas

Crie um arquivo .env.local na raiz do projeto para configurações específicas, como endereços de email de remetente e destinatário e senhas de acesso a serviços de email:


# .env.local

APP_SECRET=your_secret_key_here
DATABASE_URL=mysql://user:password@127.0.0.1:3306/db_name
MAILER_URL=smtp://user:password@smtp.gmail.com:587?retry=1&auth_mode=login&encryption=tls
EMAIL_SENDER=sender@mail.com
EMAIL_RECIPIENT=recipient@mail.com

No exemplo acima, estamos configurando as variáveis de ambiente APP_SECRET, DATABASE_URL, MAILER_URL, EMAIL_SENDER e EMAIL_RECIPIENT. Note que é necessário configurar as credenciais de acesso ao serviço de email (MAILER_URL).

Passo 8 – Criação da classe de exceção personalizada (se necessário)

Se você deseja criar uma classe de exceção personalizada para lidar com erros específicos, crie a classe desejada que estenda a classe “Exception” ou “Throwable” do PHP:


# src/Exception/CustomException.php

namespace AppException;

class CustomException extends Exception
{
// Métodos e propriedades da classe
}

Passo 9 – Criação do arquivo de rotas para páginas de erro personalizadas (se necessário)

Se você deseja exibir páginas de erro personalizadas, crie um arquivo de rotas (por exemplo, “exceptions.yaml”) no diretório “/config/routes/” para definir as rotas das páginas de erro desejadas:


# config/routes/exceptions.yaml

errors:
path: /error
controller: AppControllerExceptionController::showError

error404:
path: /error404
controller: AppControllerExceptionController::showNotFound

error500:
path: /error500
controller: AppControllerExceptionController::showInternalServerError

No exemplo acima, estamos definindo as rotas “/error”, “/error404” e “/error500” para apresentação das páginas de erro personalizadas correspondentes. Estas rotas são tratadas pelo controller “AppControllerExceptionController”.

Passo 10 – Criação do controller de tratamento de erros personalizado

Crie uma classe de controller de tratamento de erros personalizado que estenda a classe “SymfonyBundleFrameworkBundleControllerAbstractController”. Este controller será responsável por lidar com os erros que ocorrerem na aplicação e pode ser configurado no arquivo config/routes.yaml:


# config/routes.yaml

_errors:
resource: '@App/Controller/ExceptionController.php'
type: annotation

Neste exemplo, estamos configurando o controller “AppControllerExceptionController” para lidar com as rotas de erro. Este controller pode ser personalizado de acordo com as necessidades da aplicação.

Passo 11 – Configuração do controller para exibir informações de debug em ambiente de desenvolvimento

Se a aplicação estiver em ambiente de desenvolvimento e você desejar exibir informações de debug nos erros, inclua o seguinte trecho de código no seu controller:


# src/Controller/ExceptionController.php

use SymfonyComponentHttpKernelExceptionHttpExceptionInterface;
use SymfonyComponentHttpFoundationResponse;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentHttpFoundationJsonResponse;
use SymfonyBundleFrameworkBundleControllerAbstractController;

class ExceptionController extends AbstractController
{
...
protected function showException(Request $request, Throwable $exception, $statusCode, $erroMessage = '')
{
if ($this->getParameter('kernel.environment') === 'dev') {
$response = new JsonResponse([
'code' => $statusCode,
'message' => $erroMessage,
'error' => $exception->getMessage()
], $statusCode);

return $response;
}
...
}
...
}

Este trecho de código verifica se a aplicação está em ambiente de desenvolvimento (if ($this->getParameter(‘kernel.environment’) === ‘dev’)) e, em caso positivo, retorna uma resposta em JSON contendo informações de debug. Note que este exemplo apresenta apenas a parte relevante do código do controller.

Passo 12 – Configuração do controller para lidar com erros 404

Configure o controller de tratamento de erros personalizado para lidar com erros 404 de acordo com as necessidades da aplicação. Um exemplo de implementação é o seguinte:


# src/Controller/ExceptionController.php

use SymfonyComponentHttpKernelExceptionHttpExceptionInterface;
use SymfonyComponentHttpFoundationResponse;
use SymfonyComponentHttpFoundationRequest;
use SymfonyBundleFrameworkBundleControllerAbstractController;

class ExceptionController extends AbstractController
{
...
protected function showNotFound(Request $request, HttpExceptionInterface $exception)
{
return $this->render('bundles/TwigBundle/Exception/404.html.twig', [
'error' => $exception
]);
}
...
}

Neste exemplo, estamos exibindo a página de erro 404 (404.html.twig) para o usuário e passando a mensagem de erro original como parâmetro para a view (‘error’ => $exception).

Passo 13 – Configuração do controller para lidar com erros 500

Configure o controller de tratamento de erros personalizado para lidar com erros 500 de acordo com as necessidades da aplicação. Um exemplo de implementação é o seguinte:


# src/Controller/ExceptionController.php

use SymfonyComponentHttpKernelExceptionHttpExceptionInterface;
use SymfonyComponentHttpFoundationResponse;
use SymfonyComponentHttpFoundationRequest;
use SymfonyBundleFrameworkBundleControllerAbstractController;

class ExceptionController extends AbstractController
{
...
protected function showInternalServerError(Request $request, HttpExceptionInterface $exception)
{
return $this->render('bundles/TwigBundle/Exception/500.html.twig', [
'error' => $exception
]);
}
...
}

Neste exemplo, estamos exibindo a página de erro 500 (500.html.twig) para o usuário e passando a mensagem de erro original como parâmetro para a view (‘error’ => $exception).

Passo 14 – Configuração do controller para lidar com erros genéricos

Configure o controller de tratamento de erros personalizado para lidar com erros genéricos de acordo com as necessidades da aplicação. Um exemplo de implementação é o seguinte:


# src/Controller/ExceptionController.php

use SymfonyComponentHttpKernelExceptionHttpExceptionInterface;
use SymfonyComponentHttpFoundationResponse;
use SymfonyComponentHttpFoundationRequest;
use SymfonyBundleFrameworkBundleControllerAbstractController;

class ExceptionController extends AbstractController
{
...
protected function showError(Request $request, Throwable $exception)
{
$