php · level 3 · unit 4 · lesson 3
- meet it
- guess first
- your turn
- fix it
- nailed it
Tap a green word if you get lost.
meet it
An exception can carry extra details, and even another exception.
A message is only text, but a form wants to know which field failed. Give your exception a constructor with an extra readonly property, then hand the message on with parent::__construct($message) so that getMessage() still works.
When a low-level error bubbles up, like a database complaint, it: catch it and throw your own clearer exception, passing the original as the third argument, as in new StorageFailed("...", 0, $e). The 0 is a number code. Later, getPrevious() hands the original back. Linked like this, they form an .
<?php
class InvalidField extends InvalidArgumentException {
public function __construct(public readonly string $field, string $message) {
parent::__construct($message);
}
}
function checkEmail(string $email): void {
if (filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
throw new InvalidField("email", "That email does not look right.");
}
}
try {
checkEmail("mia-at-example");
} catch (InvalidField $e) {
echo "Field '$e->field': " . $e->getMessage() . "\n";
} A form can now put each message beside the right box, because it knows $e->field.
guess first
A missing table, wrapped up. What will this show?
Guess before you run it. Wrong guesses are how you learn, and nothing is marked.
<?php
class StorageFailed extends RuntimeException {}
function emptyBasket(PDO $db): void {
try {
$db->exec("DELETE FROM basket");
} catch (PDOException $e) {
throw new StorageFailed("Could not empty the basket.", 0, $e);
}
}
try {
emptyBasket(new PDO("sqlite::memory:"));
} catch (StorageFailed $e) {
echo $e->getMessage() . "\n";
echo get_class($e->getPrevious()) . "\n";
}
your turn
Your turn. Tell the shopper how far over budget they are.
Type a price and a budget, both in pence. Try a price above the budget to see the exception carry its extra detail.
fix it
The form says there is a problem, but not what. Fix it.
- No crash, but the message is empty. Line 5 pretends a form was sent with a blank name. Where should the words come from?
- The constructor stores
$fieldbut never passes a message on to the parent, sogetMessage()has nothing to give. - Inside the constructor's curly brackets, add
parent::__construct("Please fill in $field.");, then run it.
nailed it
your exceptions carry the full story. :D
- Extra readonly properties let an exception carry useful details.
- Call
parent::__construct($message)sogetMessage()still works. - Wrap low-level errors, passing the original as the third argument.
new words in your collection
- wrap
- exception chain
This lesson isn’t saved. A free account remembers every lesson you finish.