Você não deve capturar a exceção, a menos que pretenda fazer algo significativo .
"Algo significativo" pode ser um dos seguintes:
Manipulando a exceção
A ação significativa mais óbvia é lidar com a exceção, por exemplo, exibindo uma mensagem de erro e interrompendo a operação:
try {
$connect = new CONNECT($db, $user, $password, $driver, $host);
}
catch (Exception $e) {
echo "Error while connecting to database!";
die;
}
Log ou limpeza parcial
Às vezes, você não sabe como lidar adequadamente com uma exceção dentro de um contexto específico; talvez você não tenha informações sobre o "quadro geral", mas deseja registrar a falha o mais próximo possível do possível. Nesse caso, convém capturar, registrar e lançar novamente:
try {
$connect = new CONNECT($db, $user, $password, $driver, $host);
}
catch (Exception $e) {
logException($e); // does something
throw $e;
}
Um cenário relacionado é onde você está no lugar certo para executar uma limpeza na operação com falha, mas não para decidir como a falha deve ser tratada no nível superior. Nas versões anteriores do PHP, isso seria implementado como
$connect = new CONNECT($db, $user, $password, $driver, $host);
try {
$connect->insertSomeRecord();
}
catch (Exception $e) {
$connect->disconnect(); // we don't want to keep the connection open anymore
throw $e; // but we also don't know how to respond to the failure
}
O PHP 5.5 introduziu a finallypalavra - chave, portanto, para cenários de limpeza, agora existe outra maneira de abordar isso. Se o código de limpeza precisar executar, não importa o que aconteceu (por exemplo, com erro e com êxito), agora é possível fazer isso, permitindo com transparência a propagação de qualquer exceção lançada:
$connect = new CONNECT($db, $user, $password, $driver, $host);
try {
$connect->insertSomeRecord();
}
finally {
$connect->disconnect(); // no matter what
}
Abstração de erro (com encadeamento de exceção)
Um terceiro caso é onde você deseja agrupar logicamente muitas possíveis falhas sob um guarda-chuva maior. Um exemplo para agrupamento lógico:
class ComponentInitException extends Exception {
// public constructors etc as in Exception
}
class Component {
public function __construct() {
try {
$connect = new CONNECT($db, $user, $password, $driver, $host);
}
catch (Exception $e) {
throw new ComponentInitException($e->getMessage(), $e->getCode(), $e);
}
}
}
Nesse caso, você não deseja que os usuários Componentsaibam que ela é implementada usando uma conexão com o banco de dados (talvez você queira manter suas opções abertas e usar o armazenamento baseado em arquivo no futuro). Portanto, sua especificação Componentdiria que "no caso de uma falha de inicialização, ComponentInitExceptionserá lançada". Isso permite que os consumidores Componentcapturem exceções do tipo esperado , além de permitir que o código de depuração acesse todos os detalhes (dependentes da implementação) .
Fornecendo um contexto mais rico (com encadeamento de exceção)
Finalmente, há casos em que você pode fornecer mais contexto para a exceção. Nesse caso, faz sentido agrupar a exceção em outra que contém mais informações sobre o que você estava tentando fazer quando ocorreu o erro. Por exemplo:
class FileOperation {
public static function copyFiles() {
try {
$copier = new FileCopier(); // the constructor may throw
// this may throw if the files do no not exist
$copier->ensureSourceFilesExist();
// this may throw if the directory cannot be created
$copier->createTargetDirectory();
// this may throw if copying a file fails
$copier->performCopy();
}
catch (Exception $e) {
throw new Exception("Could not perform copy operation.", 0, $e);
}
}
}
Este caso é semelhante ao acima (e o exemplo provavelmente não é o melhor possível), mas ilustra o ponto de fornecer mais contexto: se uma exceção for lançada, ele nos informa que a cópia do arquivo falhou. Mas por que falhou? Essas informações são fornecidas nas exceções agrupadas (das quais poderia haver mais de um nível, se o exemplo fosse muito mais complicado).
O valor de fazer isso é ilustrado se você pensar em um cenário em que, por exemplo, a criação de um UserProfileobjeto faz com que os arquivos sejam copiados porque o perfil do usuário é armazenado em arquivos e suporta a semântica de transações: você pode "desfazer" as alterações porque elas são executadas apenas em um ambiente. cópia do perfil até você confirmar.
Nesse caso, se você fez
try {
$profile = UserProfile::getInstance();
}
e, como resultado, ocorreu um erro de exceção "O diretório de destino não pôde ser criado", você teria o direito de ficar confuso. O agrupamento dessa exceção "principal" em camadas de outras exceções que fornecem contexto tornará o erro muito mais fácil de lidar ("Falha na criação da cópia do perfil" -> "Falha na operação de cópia do arquivo" -> "O diretório de destino não pôde ser criado").