Podstawy exception handling w PHP – pisanie własnych Errorów, rzucanie i łapanie ich oraz obsługa. Do dzieła.

Piszemy customowy exception bazując na najbardziej ogólnej klasie:

class ContainerException extends Exception
{
}

Teraz funkcja, która może wyrzucić exception (ta zawsze wyrzuca):

function _next($className = 'FakeCls', $name = 'FakeParam'){
    throw new ContainerException("Failed to resolve class {$className} because param {$name} is missing a type hint.");
}

Teraz obsługa poprzez blok try-catch:

try {
    _next();
} catch (ContainerException $e) {
    echo $e->getMessage();
}
//Failed to resolve class FakeCls because param FakeParam is missing a type hint.

Teraz ValidationException, czyli coś, co może być rzucone podczas run-time:

class ValidationException extends RuntimeException
{
  public function __construct(public array $errors, int $code = 422)
  {
    parent::__construct(code: $code);
  }
}

Jak widać zarówno promocja przez konstruktor jak i „tradycyjne” wołanie konstruktora a nawet konstruktora-rodzica.

Teraz nasza pseudo-funkcja:

function _next(){
    $errors = [
        'name' => 'Must be uniqe!',
        'email' => 'Email already taken!',
        'password' => 'Must be at least 8 characters long!'
    ];
    if (count($errors)) {
        throw new ValidationException($errors);
      }
}

Próbujemy wywołać _next, jeżeli error, to zapisujemy errory do sesji (plus wyświetlamy je):

try {
    _next();
} catch (ValidationException $e) {
    
    $_SESSION['errors'] = $e->errors;
    print_r($_SESSION['errors']);
}

// Array ( 
//     [name] => Must be uniqe! 
//     [email] => Email already taken! 
//     [password] => Must be at least 8 characters long! 
//     )

Może się wydawać, że obsługa błędów jest łatwa, ale nic z tych rzeczy – są własne error-handlery i exception-handlery, łatwe to to może wydawać się przedstawione w ten sposób.

Tym niemniej są to podstawy, które w wielu przypadkach całkowicie wystarczą.