Lab 03: Advanced Error Handling

Objective

Build a production-grade error handling system: custom exception hierarchies, exception chaining, finally blocks for resource cleanup, a functional Result<T> type that avoids exceptions for expected failures, global error handlers, and structured error logging.

Background

PHP has two error systems: errors (old C-style: E_WARNING, E_NOTICE) and exceptions (OOP-style: throw new Exception()). Since PHP 7, most fatal errors are now Error objects that can be caught. A common mistake is using exceptions for expected failures ("product not found") — this has performance cost and poor semantics. The Result pattern encapsulates success/failure in a return value, making failure a normal code path.

Time

30 minutes

Prerequisites

  • PHP Foundations Lab 09 (Error Handling)

Tools

  • Docker: zchencow/innozverse-php:latest


Lab Instructions

Step 1: Custom exception hierarchy

💡 Exception chaining with $previous is critical for debugging. When you catch a low-level exception (e.g., a database PDOException) and re-throw a domain exception (PaymentException), always pass the original as the third parent::__construct() argument. This preserves the full stack trace chain. $e->getPrevious() retrieves it, and error logging tools like Sentry display the complete cause chain.

📸 Verified Output:


Step 2: finally for resource cleanup + Result<T> type

📸 Verified Output:


Summary

Pattern
When to use

Custom exception class

Domain-specific errors with extra context

Exception chaining ($previous)

Wrapping low-level exceptions in domain ones

finally

Resource cleanup (files, DB connections, locks)

Result<T> (`Success

Failure`)

Catch Throwable

Catch both Exception and Error

Further Reading

Last updated