Non dovresti cogliere l'eccezione se non hai intenzione di fare qualcosa di significativo .
"Qualcosa di significativo" potrebbe essere uno di questi:
Gestire l'eccezione
L'azione più ovvia e significativa è gestire l'eccezione, ad esempio visualizzando un messaggio di errore e interrompendo l'operazione:
try {
$connect = new CONNECT($db, $user, $password, $driver, $host);
}
catch (Exception $e) {
echo "Error while connecting to database!";
die;
}
Registrazione o pulizia parziale
A volte non sai come gestire correttamente un'eccezione all'interno di un contesto specifico; forse ti mancano le informazioni sul "quadro generale", ma vuoi registrare il guasto il più vicino possibile al punto in cui è successo. In questo caso, potresti voler catturare, registrare e ri-lanciare:
try {
$connect = new CONNECT($db, $user, $password, $driver, $host);
}
catch (Exception $e) {
logException($e); // does something
throw $e;
}
Uno scenario correlato è quello in cui ci si trova nel posto giusto per eseguire alcune operazioni di pulizia per l'operazione non riuscita, ma non per decidere come gestire l'errore al livello più alto. Nelle precedenti versioni di PHP questo sarebbe stato implementato come
$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
}
PHP 5.5 ha introdotto la finally
parola chiave, quindi per gli scenari di pulizia c'è ora un altro modo per affrontarlo. Se il codice di cleanup deve essere eseguito indipendentemente da ciò che è accaduto (sia in caso di errore sia in caso di successo) è ora possibile farlo consentendo in modo trasparente la propagazione di eventuali eccezioni generate:
$connect = new CONNECT($db, $user, $password, $driver, $host);
try {
$connect->insertSomeRecord();
}
finally {
$connect->disconnect(); // no matter what
}
Astrazione degli errori (con concatenamento delle eccezioni)
Un terzo caso è quello in cui si desidera raggruppare logicamente molti possibili guasti sotto un ombrello più grande. Un esempio per il raggruppamento logico:
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);
}
}
}
In questo caso, non si desidera che gli utenti Component
sappiano che è implementato utilizzando una connessione al database (forse si desidera mantenere aperte le opzioni e utilizzare l'archiviazione basata su file in futuro). Quindi la tua specifica Component
direbbe che "in caso di errore di inizializzazione, ComponentInitException
verrà lanciato". Ciò consente ai consumatori di Component
rilevare eccezioni del tipo previsto, consentendo al contempo al codice di debug di accedere a tutti i dettagli (dipendenti dall'implementazione) .
Fornire un contesto più ricco (con il concatenamento delle eccezioni)
Infine, ci sono casi in cui potresti voler fornire più contesto per l'eccezione. In questo caso ha senso racchiudere l'eccezione in un'altra che contiene ulteriori informazioni su ciò che si stava tentando di fare quando si è verificato l'errore. Per esempio:
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);
}
}
}
Questo caso è simile al precedente (e l'esempio probabilmente non è il migliore che si potrebbe trovare), ma illustra il punto di fornire più contesto: se viene generata un'eccezione, ci dice che la copia del file non è riuscita. Ma perché ha fallito? Questa informazione è fornita nelle eccezioni racchiuse (di cui potrebbe esserci più di un livello se l'esempio fosse molto più complicato).
Il valore di ciò è illustrato se si pensa a uno scenario in cui, ad esempio, la creazione di un UserProfile
oggetto provoca la copia di file perché il profilo utente è archiviato in file e supporta la semantica delle transazioni: è possibile "annullare" le modifiche perché vengono eseguite solo su un copia del profilo fino al momento del commit.
In questo caso, se lo hai fatto
try {
$profile = UserProfile::getInstance();
}
e di conseguenza è stato rilevato un errore di eccezione "Impossibile creare la directory di destinazione", si avrebbe il diritto di essere confuso. Avvolgere questa eccezione "core" in strati di altre eccezioni che forniscono il contesto renderà molto più facile gestire l'errore ("Creazione della copia del profilo non riuscita" -> "Operazione di copia del file non riuscita" -> "Impossibile creare la directory di destinazione").