An exception is an event that occurs during the execution of a program that disrupts the normal flow of instructions. PHP uses exceptions to handle errors and other exceptional events.
As in many other languages, an exception can be thrown and caught. You can throw an exception using the throw
keyword, which in PHP 8 became an expression that may be used in any expression context, while in previous versions it was a statement that had to be in its line.
To facilitate the catching of exceptions, the code should be surrounded by a try
block that must have at least one matching catch
or finally
blocks. If an exception gets thrown and its current scope doesn’t have a catchable block, the exception will “bubble up” or be sent to a “higher scope”.
If the handling of an exception implements both the catch
and finally
blocks, be advised that all finally
blocks encountered in the way of the exception event will be executed, even when the event has already passed through the catch
block.
Finally, if an exception goes all the way to the global scope without finding a matching catchable block, your code will terminate with a fatal error unless the app has a global exception handler, like the one that Laravel has.
Content
Throwing exceptions
Now that we understand the structure around exception events, let’s see a couple of examples of how we can throw and catch exceptions.
Let’s say we want to parse a PHP object to JSON; we would probably use the json_encode()
function for that. This function will not always be able to transform the given object to JSON for various reasons, and when this happens, the function will return false
to let us know that the transformation failed.
In some ways, we can say that if the transformation of the object fails, our code gets disrupted from the normal flow of instructions since we instructed the code to get us a JSON, and we got a boolean instead.
With that being said, let’s see in the example down below, how we can use an exception to trigger an event informing that something out of the normal flow has happened.
<?php
class Person
{
private $props = [];
public function __construct(
private string $name = '',
private string $lastName = ''
) {
$this->props = [
'name' => $this->name,
'last_name' => $this->lastName,
];
}
public function toJson($options = 0.0)
{
$jsonEncoded = json_encode($this->props, $options);
if ($jsonEncoded === false) {
throw new JsonEncodeException();
}
return $jsonEncoded;
}
}
The toJson()
function is responsible for transforming his class into JSON; as mentioned before, we were going to use the json_encode()
which is being called at the first line of the function and has its returned value stored at the $jsonEncoded
object.
Next, we have a conditional that checks if the $jsonEncoded
is false
, and if it is, an exception will be thrown because the normal flow of our code got disrupted.
Then, if the flow of our code didn’t get disrupted, we would just return the $jsonEncoded
object, which at this point is a JSON with the correspondent values of the props from our Person class.
The try and catch blocks
To catch the exception potentially thrown by the Person class, we have to use a try
with a matching catch
block, as the example down below shows.
try {
$person = new Person('Jack', 'Miras');
$personAsJson = $person->toJson();
} catch(JsonEncodeException $e) {
echo "Exception has been caught";
}
On the first line of the try
block, we are creating a person object, passing a name and a last name as parameters in its constructor.
Next, we call the toJson()
function out of the $person
object. If the object got correctly transformed into JSON, the $personAsJson
object would receive a JSON string as a result. Otherwise, an exception would be thrown, and the catch
block would be triggered.
Thereafter, if an exception gets thrown and the catch
block gets triggered, it would first check if the exception being intercepted is an instance of the JsonEncodeException class. If that’s the case, the catch
block would take this exception event, passing it to its handling block, which is printing a message telling that the exception has been caught.
The finally block
Another way of handling the exception potentially thrown by the Person class would be to use a finally
block to match the try
block defined, as the example below shows.
try {
$person = new Person('Jack', 'Miras');
$personAsJson = $person->toJson();
} finally {
echo "Converting person to JSON failed";
}
As in the previous example, at the try
block, we are creating a person object and calling the toJson()
function out of it. If the object gets correctly transformed, the $personAsJson
would receive a JSON string. Otherwise, an exception would be thrown.
Thereafter, if an exception gets thrown, the finally
block will be triggered even though a catch block has already handled the exception event.
If that’s the case, the finally
block would take in this exception event and print a message telling that the conversion of the person object into JSON failed.
Now that you have a more in-depth understanding of what exceptions are and what they are used for, it’s time for us to move on to the next post in this series.
Happy coding!
Top comments (3)
Can't believe I didn't know about the
finally
block (you've got a typo in your code block, by the way –finnaly
)Thanks for the heads-up, I've fixed the typo.
A third and a fourth part of this series will be published in the coming weeks, there is more content there that you may find interesting… In case you have the time, don't forget to check it out.
finally
always gets called regardless of whether an exception was thrown. In this example you'll always get the error, even if toJson works.