Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Laravel/Lumen, why is the catch block not catching my Exception?

What's the best way to catch an Exception in the Laravel/Lumen PHP framework? This is most likely a question which applies to PHP in general.

Presently, I have a UsersController that calls (in the try block) the 'findByUsernameOrFail' method in my User class. This method will throw an Exception if the username can't be found, but the catch block is not catching the Exception! Why?

class UsersController extends Controller {

    public function show($username)
    {
        try
        {
            $user = \App\User::findByUsernameOrFail($username);

            return $user;
        }
        catch(Exception $e)
        {
            // This doesn't work. This code is never called because Laravel 
            return $this->setStatusCode(404)->respondWithError('Username Not Found!');
        }
    }

The 'show' method in this UsersController is calling a method called 'findByUsernameOrFail' in the User model. If it finds a User by the username, it returns the found $user object. If it doesn't find a User by the username, it throws an exception. However, for some reason, this Exception is not being caught, and instead Laravel is generating a generic error page.

Here's some code in my User Model:

class User extends Illuminate\Database\Eloquent\Model {

    public static function findByUsernameOrFail($username)
    {
        if ( ! is_null($user = static::whereUsername($username)->first()))
        {
            return $user;
        }

        throw new Illuminate\Database\Eloquent\ModelNotFoundException;
    }
}

And here's a screenshot of what happens when I try to run this:

enter image description here

WHY is the 'catch' part of my code never executed!? What I WANT to happen is for my app to gracefully return a HTTP 404 error that says that the User cannot be found! Based on what I've learned about Try/Catch and Exceptions, my code should work, but apparently I am missing something.

How can I get this code to return a HTTP 404 error message as intended by this code?

like image 204
skcin7 Avatar asked Feb 08 '23 16:02

skcin7


1 Answers

As suggested, you may need to explicitly declare what exception you're listening for. So correct way would be

catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
     // do your stuff.
} 

But in Laravel you can go beyond this and make it very abstract (like with pretty much everything in Laravel)

If you open app/Exceptions/Handler.php in the render method you may listen for various exceptions being thrown in your entire application.

So for you particular case it might be as follows:

if ($e instanceof ModelNotFoundException) {
    abort(404);
}

(Don't forget to import the full path at the top)


As mentioned by @Phroggyy, you may inline your code be leveraging Laravel's findOrFail() method. Behind the scenes it will do exactly what you are doing manually - try to find a model and throw an exception if not found.

like image 200
Almazik G Avatar answered Feb 11 '23 17:02

Almazik G