PHP exceptions: throw, try/catch and custom exceptions
An exception signals that a function cannot do its job: you throw it with throw, and the code that knows what to do about the error catches it with try/catch.
class ArticleIntrouvable extends Exception { public function __construct(public readonly string $slug) { parent::__construct("No article has the slug “{$slug}”."); } } /** @param array<string, Article> $articles */ function trouverArticle(array $articles, string $slug): Article { return $articles[$slug] ?? throw new ArticleIntrouvable($slug); } try { echo Page::article(trouverArticle($articles, $slug)); } catch (ArticleIntrouvable) { http_response_code(404); echo Page::introuvable(); }
As soon as throw runs, the function stops, and PHP goes back up the calls to the first catch that accepts this type of exception. Without a catch, the script stops with an “Uncaught …” fatal error. The benefit: the function that detects the problem doesn't need to know how to respond to it (404 page, message, log), and it doesn't have to return a dummy value like null or false that the caller would forget to check.
A custom exception extends Exception (or one of its subclasses) to give the error a precise name and carry the useful information, here the slug. You then catch exactly what you know how to handle, and everything else keeps going up. Since PHP 8.0, catch (ArticleIntrouvable) can be written without a variable when you don't use it.
2 exercises work on this concept, by writing code in the browser.