Courses

PHP for Laravel Developers

Try-Catching Exceptions and PHP Errors

Summary of this lesson:
- Learn about try-catch block usage
- Understand custom exception creation
- Explore global exception handling
- Examine differences between exceptions and errors

Exceptions are the mechanism to catch some invalid behavior and gracefully handle them instead of just showing "500 server error" to the users.

Take a look at this example:

public function __invoke()
{
$data = [['name' => 'John Doe', 'email' => '[email protected]', 'date' => '23-04']];
 
try {
$this->import($data);
} catch (ImportHasMalformedData $e) {
return redirect()->route('dashboard')->with('message', 'Uh oh, the import has failed. Try again later or contact support');
}
 
return 'Imported';
}

This snippet means that in case of ANY Exception, the user would get redirected back and see the error message.

But what if we're expecting something specific to happen?


Catching a Specific Laravel Exception

Try-catch is way more helpful when catching a specific Exception. Laravel and 3rd party packages often offer us actionable Exception classes for particular errors.

For example, when uploading a picture, you might have some issues with resizing the image. For that, there's a specific InvalidManipulation.

use Spatie\Image\Exceptions\InvalidManipulation;
use Exception;
 
try {
$request->user()->addMediaFromRequest('avatar')->toMediaCollection();
} catch (InvalidManipulation $manipulationException) {
Log::debug($manipulationException->getMessage());
 
Log::info("Please re-run the resizing on user avatar #" . $request->user()->id);
}

Globally Processing Specific Exception

There are cases when, for a specific Exception, you will always want to render the same result.

For example, only for routes with /api and if Exception is NotFoundHttpException to show some general message.

app/Exceptions/Handler.php:

use Illuminate\Http\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 
class Handler extends ExceptionHandler
{
// ...
 
public function register(): void
{
$this->renderable(function (NotFoundHttpException $e, Request $request) {
if ($request->is('api/*')) {
return response()->json(['message' => 'Record not found.'], 404);
}
});
}
 
// ...
}

Creating Your Own Exception Class

To create a custom Exception in Laravel, you need to run a single command:

php artisan make:exception ImportHasMalformedData

It will create a new file in app/Exceptions/ImportHasMalformedData.php.

app/Exceptions/ImportHasMalformedData.php:

class ImportHasMalformedData extends Exception
{
protected $message = 'The import has malformed data.';
}

Now, throwing this Exception will result in a more actionable message:

use App\Exceptions\ImportHasMalformedData;
 
// ...
 
public function __invoke()
{
$data = [['name' => 'John Doe', 'email' => '[email protected]', 'date' => '23-04']];
 
try {
$this->import($data);
} catch (ImportHasMalformedData $e) {
return 'Malformed data';
}
 
return 'Imported';
}

Running this, we will have the following output in our browser:

Malformed data

PHP Errors vs Exceptions

In addition to Exceptions, there are also PHP errors to catch, those are different things! Sometimes, you need to handle PHP errors. For example, this message:

While this isn't an Exception, you can still manage them like they are.

try {
$this->importData();
} catch (\Exception $e) {
dd("General Exception: " . $e->getMessage());
} catch (\Error $e) {
dd("General error: " . $e->getMessage());
}
public function importData($row)
{
// ...
}

That way, you can catch the PHP Error just like an Exception:

You can do this for all the errors in the official PHP documentation.

Previous: Variable Types and Return Types
avatar

In the first example provided, you use the method import ($data) $this->import($data), however, in your last try catch statement, you use ImportController::importData(). Is there a connection between the 2 import methods? Does this mean that the ImportController has a static method called importData() and a regular method called import($data)? Are they the same thing (does laravel 'know' a method + a parameter can be directly called as methodParameter())? Or is this a typo?

avatar

No, it's a basic method in this case, not static. This part is taken from the Handling Exceptions and Errors in Laravel so better refer there for more about exceptions.

avatar

Thank you very much!

avatar
You can use Markdown
avatar

It would be appropriate to provide information about the "finally" block.

Code within the finally block will always be executed after the try and catch blocks, regardless of whether an exception has been thrown, and before normal execution resumes. https://www.php.net/manual/en/language.exceptions.php#language.exceptions.finally

👍 1
avatar

This course/lesson was more focused on the PHP errors and not on overall error handling. We have a separate tutorial about the exceptions, where we talk about finally there :)

avatar
You can use Markdown
avatar
You can use Markdown