sdexp
sdexp

Reputation: 776

How do I deal with Exceptions in Laravel 5.4?

I'm using Laravel 5.4 and I'm using Stripe as a payment processor.

The Stripe side seems to be working but I'm struggling with the exceptions. The code below seemed to be working before, but maybe it was using files from the cache that have since been cleared:

namespace App\Http\Controllers;

// Do I need to use anything at the top??
// use Exception; 

class ItemController extends Controller
{
    public function postCheckout(Request $request, Exception $e)
    {
        if ($e instanceof \Illuminate\Session\TokenMismatchException) {
            return redirect()->back()->withInput()->with(
                'token', csrf_token()
            );
        }

        try {
            // ...
        } catch (\Exception $e) {
            return redirect()->route('checkout')->with(
                'error', $e->getMessage()
            );
        }
    }
}

Which gives the error:

(1/1) ReflectionException
Class App\Http\Controllers\Exception does not exist
in RouteSignatureParameters.php (line 25)

If I remove the Exception $e parameter from the method, and comment out the if and try statements the successful payment is dealt with as expected.

What am I doing wrong here?

EDIT

If I say \Exception $e I get:

(1/1) BindingResolutionException
Unresolvable dependency resolving [Parameter #0 [ <optional> $message ]] in class Exception
in Container.php (line 910)

Upvotes: 1

Views: 1434

Answers (1)

Risan Bagja Pradana
Risan Bagja Pradana

Reputation: 4674

Let's learn about namespace and type-hinting in PHP. If you code it like this:

namespace App\Http\Controllers;

class ItemController extends Controller
{
    public function postCheckout(Request $request, Exception $e)
    {
        ...
    }
}

That means your postCheckout method expect the second argument to be an instance of class App\Http\Controllers\Exception. That's why you got an error like this if this exception class does not exist:

Class App\Http\Controllers\Exception does not exist

I'm not sure in about your case because I don't know how this postCheckout method being called from another part of your code. But if you're expecting the second parameter to be the built-in PHP Exception class, you can do it with full-path namespace like this:

namespace App\Http\Controllers;

class ItemController extends Controller
{
    public function postCheckout(Request $request, \Exception $e)
    {
        ...
    }
}

Or you can also import the intended class namespace above:

use Exception;
namespace App\Http\Controllers;

class ItemController extends Controller
{
    public function postCheckout(Request $request, Exception $e)
    {
        ...
    }
}

And the second error happened because of Laravel's container unable to resolve the dependencies required by the postCheckout method.

(1/1) BindingResolutionException
Unresolvable dependency resolving...

From this error and the name of your class, I'm assuming you use this postCheckout method as route handler?

Route::post('/foo', 'ItemController@postCheckout');

If this is the case, then that's not how you catch the exception with Laravel. To handle exception in Laravel, you can do it within the app/Exceptions/Handler.php file. There are two methods there:

  1. report: If you want to log the exception with custom format.
  2. render: If you want to return a custom HTTP response to that exception.

In your case, you want a custom response:

public function render($request, Exception $exception)
{
    if ($exception instanceof \Illuminate\Session\TokenMismatchException) {
        // Perform the exception handler here
    }

    return parent::render($request, $exception);
}

The same thing also applied to your Stripe related exception, you can handle it within this Handler class. Read more about The render Method.

Hope this gives you some ideas.

Upvotes: 1

Related Questions