Try, Catch, Finally
Parte de la sección Programación Orientada a Objetos del Journey de PHP de Coddy — lección 68 de 91.
Ahora que sabes cómo crear y lanzar excepciones, necesitas aprender cómo capturarlas. La estructura try-catch-finally te permite manejar excepciones de manera elegante en lugar de dejar que bloqueen tu aplicación.
Envuelve el código que podría lanzar una excepción en un bloque try, luego maneja la excepción en un bloque catch:
<?php
class Calculator {
public function divide(int $a, int $b): float {
if ($b === 0) {
throw new InvalidArgumentException("Cannot divide by zero");
}
return $a / $b;
}
}
$calc = new Calculator();
try {
echo $calc->divide(10, 0);
} catch (InvalidArgumentException $e) {
echo "Error: " . $e->getMessage();
}
Salida:
Error: Cannot divide by zeroPuedes capturar diferentes tipos de excepciones con múltiples bloques catch. PHP las comprueba en orden, así que coloca primero las excepciones más específicas:
<?php
try {
// código arriesgado
} catch (InvalidArgumentException $e) {
echo "Bad input: " . $e->getMessage();
} catch (Exception $e) {
echo "Something went wrong: " . $e->getMessage();
}
El bloque finally se ejecuta independientemente de si se lanzó o se capturó una excepción. Es perfecto para tareas de limpieza como cerrar conexiones:
<?php
try {
echo "Attempting operation\n";
throw new Exception("Failed");
} catch (Exception $e) {
echo "Caught: " . $e->getMessage() . "\n";
} finally {
echo "Cleanup complete";
}
Salida:
Attempting operation
Caught: Failed
Cleanup completeEl bloque finally se ejecuta incluso si realizas un return desde dentro de los bloques try o catch, lo que lo hace confiable para operaciones de limpieza esenciales.
Desafío
FácilVamos a construir un sistema de procesamiento de archivos que demuestre cómo try-catch-finally trabajan juntos para manejar errores con elegancia mientras se asegura que la limpieza siempre ocurra.
Organizarás tu código en tres archivos:
FileException.php— Crea una clase personalizadaFileExceptionque extienda deException. Esto representará errores relacionados con archivos en tu sistema.FileProcessor.php— Crea una claseFileProcessorque simule operaciones de archivos. Incluye el archivo FileException. Tu clase debe tener:- Una propiedad booleana privada
$isOpeninicializada enfalse - Un método
open(string $filename): voidque establezca$isOpenentruee imprima"Opening: [filename]". Si el nombre del archivo es"invalid.txt", lanza unaFileExceptioncon el mensaje"Cannot open file" - Un método
process(): voidque imprima"Processing file...". Si$isOpenesfalse, lanza unaRuntimeExceptioncon el mensaje"File not open" - Un método
close(): voidque establezca$isOpenenfalsee imprima"File closed" - Un método
isOpen(): boolque devuelva el estado actual
- Una propiedad booleana privada
main.php— Incluye el archivo FileProcessor. Recibirás una entrada: un nombre de archivo.Crea un
FileProcessory utiliza una estructuratry-catch-finallypara:- En el bloque
try: llama aopen()con el nombre del archivo, luego llama aprocess() - Captura
FileExceptionprimero e imprime"File error: [message]" - Captura
RuntimeExceptione imprime"Runtime error: [message]" - En el bloque
finally: verifica si el archivo está abierto usandoisOpen(), y si es así, llama aclose(). Luego imprime"Cleanup complete"
- En el bloque
El bloque finally asegura que la limpieza ocurra ya sea que las operaciones tengan éxito o fallen. Este patrón es esencial para gestionar recursos como archivos, conexiones a bases de datos o sockets de red donde la limpieza debe ocurrir independientemente de lo que suceda durante el procesamiento.
Hoja de referencia
Usa try-catch-finally para manejar excepciones de manera elegante y asegurar que el código de limpieza siempre se ejecute:
<?php
try {
// código que podría lanzar una excepción
} catch (ExceptionType $e) {
// manejar la excepción
echo $e->getMessage();
}
Captura múltiples tipos de excepciones con bloques catch separados. Coloca las excepciones más específicas primero:
<?php
try {
// código arriesgado
} catch (InvalidArgumentException $e) {
echo "Bad input: " . $e->getMessage();
} catch (Exception $e) {
echo "Something went wrong: " . $e->getMessage();
}
El bloque finally se ejecuta independientemente de si se lanzó o capturó una excepción, lo que lo hace ideal para operaciones de limpieza:
<?php
try {
// intentar operación
} catch (Exception $e) {
// manejar error
} finally {
// el código de limpieza siempre se ejecuta
}
Pruébalo tú mismo
<?php
require_once 'FileProcessor.php';
// Leer entrada
$filename = trim(fgets(STDIN));
// TODO: Crear una instancia de FileProcessor
// TODO: Usar la estructura try-catch-finally:
// - En el bloque try: llamar a open() con el nombre del archivo, luego llamar a process()
// - Capturar FileException primero e imprimir "File error: [message]"
// - Capturar RuntimeException e imprimir "Runtime error: [message]"
// - En el bloque finally: verificar si el archivo está abierto usando isOpen(), si es así llamar a close()
// Luego imprimir "Cleanup complete"
?>Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de OOP
Archivos externosIntroducción a OOPClases vs ObjetosLa palabra clave $thisMétodosPropiedadesConstructor (__construct)Destructor (__destruct)Resumen - Calculadora simple4Herencia
Herencia básicaLa palabra clave parent::Sobrescritura de métodosLa palabra clave finalClases abstractasResumen - Jerarquía de empleados7Encapsulamiento
Público, Protegido, PrivadoModificadores de acceso a fondoGetters y SettersOcultamiento de informaciónPromoción de constructor (8.0)Resumen - Sistema de registros de estudiantes10Conceptos avanzados de POO
Composición vs. HerenciaInyección de dependenciasClases anónimasEnums (PHP 8.1)Fibers (PHP 8.1)Clonación de objetos a fondoGeneradores e Iteradores13Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón Repository2Espacios de nombres y Autoloading
Introducción a los espacios de nombresLa palabra clave useEstándar de Autoloading PSR-4Autoloader de ComposerResumen - Proyecto organizado5Interfaces y Contratos
Introducción a las InterfacesImplementación de InterfacesImplementación de Múltiples InterfacesInterfaz vs Clase AbstractaType Hinting con InterfacesResumen - Calculadora de Formas8Métodos mágicos
Introducción a los métodos mágicos__toString y __debugInfo__get, __set, __isset, __unset__call y __callStatic__clone y clonación de objetos__serialize y __unserializeResumen - Colección personalizada11Sistema de tipos y manejo de errores
Declaraciones de tiposTipos anulablesTipos de unión e intersecciónClases de excepciónJerarquía de excepciones personalizadasTry, Catch, FinallyResumen - Validador de formularios3Propiedades de clase
Propiedades de instancia vs. estáticasConstantes en clasesMétodos y propiedades estáticosPropiedades privadas y protegidasPropiedades de solo lectura (PHP 8.1)Resumen - Gestor de cuenta bancaria6Polimorfismo
Sobrescritura de métodos revisadaPolimorfismo mediante interfacesType Hinting y tipos de uniónEnlace estático tardíoResumen - Procesador de pagos9Traits
Introducción a los TraitsUso de múltiples TraitsResolución de conflictos de TraitsMétodos abstractos en TraitsTraits frente a herencia12Patrones de diseño Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón Strategy