4

I am working with Laravel and try to use try/catch as I would do for java. Unfortunately, it doesn't work as expected... The exception isn't catched, and instead of returning an error message, it makes a 422 exception.

Here is my function:

public function changePassword(Request $request){

        try{
            if (!(Hash::check($request->get('currentpassword'), Auth::user()->password))) {
                return "Your current password does not matches with the password you provided. Please try again.";
            }

            if(strcmp($request->get('currentpassword'), $request->get('new-password')) == 0){
                return "New Password cannot be same as your current password. Please choose a different password.";
            }

            $validatedData = $request->validate([
                'currentpassword' => 'required',
                'newpassword' => 'required|string|min:6',
            ]);

            $user = Auth::user();
            $user->password = bcrypt($request->get('newpassword'));
            $user->save();

            return "Password changed successfully !";
        }
        catch(Exception $error){
            return $error->getMessage();
        }
   }

I call this method like this

Route::post('memberform/changePassword','MemberController@changePassword')->name('changePassword');

Here i would like to get my exception message, and display it. Instead, I get an error while using my request, and this exception isn't catched

422 Unprocessable Entity {"message":"The given data was invalid.","errors":{"newpassword":["The newpassword must be at least 6 characters."]}}

Thanks a lot

1
  • How are you sending the request? Commented Jun 27, 2019 at 18:12

5 Answers 5

2

Your error handling code is correct. Your code for catching an Exception is the way to do it in PHP and it works the same way as in Java (I have coded both). In short there is nothing wrong with your code.

My guess is one of two things, and I'm not 100% certain of either of them:

1) You are testing on OSX and some XDebug settings can cause problem with error handling when things are massively nested (I personally experienced this in migrations). SO XDebug settings problem

2) Laravel has an interceptor that catches the error when it occurs and that handler has been injected to take precedence before your handler. SO form validation exception not catching

Hopefully this will nudge you in the right direction. I'm sorry this is a non-answer type answer.

Sign up to request clarification or add additional context in comments.

1 Comment

This is correct because anywhere you write exception handler and even if you throw your exception the stupid framework catches it and never allows the user defined exception handler to run
2

Laravel validation fail doesn't throw exception !! So you can't catch.... If you want to catch , use custom validation like below and throw exception yourself

public function changePassword(Request $request)
{
    try
    {
       $data['currentpassword'] = $request->get('currentpassword');
       $data['newpassword'] = $request->get('newpassword');
        if (!(Hash::check($request->get('currentpassword'), Auth::user()->password))) {
            $message['currentpassword.required'] = "Your current password does not matches with the password you provided. Please try again.";
            $data['currentpassword'] = ""; // I used for required rule as a example , but I recommend to create custom rule for this
        }

        if(strcmp($request->get('currentpassword'), $request->get('new-password')) == 0){
            $message['newpassword.required'] = "New Password cannot be same as your current password. Please choose a different password.";
            $data['newpassword'] = "";// I used for required rule as a example , but I recommend to create custom rule for this
        }

        $rule = [
            'currentpassword' => 'required',
            'newpassword' => 'required|string|min:6',
        ];
        $validatedData = \Illuminate\Support\Facades\Validator::make($data, $rule, $message);
        if($validateData->fails()) {
           throw new \Exception($validateData->messages());
        }

        $user = Auth::user();
        $user->password = bcrypt($request->get('newpassword'));
        $user->save();

        return "Password changed successfully !";
    }
    catch(Exception $error)
    {
        return $error->getMessage();
    }
}

2 Comments

The validate() method that is being used throws a ValidationException. Have a look in the Validator class (located in vendor/laravel/framework/src/Illuminate/Validation/Validatot on Laravel 5.6).
What ever throw ! You will get same message I tested on laravel and used it
1

Use getMessage() method.eg:-

$error->getMessage();

Use this in catch block. It will work for you. Enjoy!!

1 Comment

Thanks a lot but it doesn't really "catch" the exception: my POST request returns an exception: app.js:800 POST 127.0.0.1/memberform/changePassword 422 (Unprocessable Entity) app.js:Uncaught (in promise) Error: Request failed with status code 422 at createError
1

You can try this

public function changePassword(Request $request){

        try{
            if (!(Hash::check($request->get('currentpassword'), Auth::user()->password))) {
                return "Your current password does not matches with the password you provided. Please try again.";
            }

            if(strcmp($request->get('currentpassword'), $request->get('new-password')) == 0){
                return "New Password cannot be same as your current password. Please choose a different password.";
            }

            $validatedData = $request->validate([
                'currentpassword' => 'required',
                'newpassword' => 'required|string|min:6',
            ]);

            $user = Auth::user();
            $user->password = bcrypt($request->get('newpassword'));
            $user->save();

            return "Password changed successfully !";
        }
        catch(\Exception $error){
            return $error->getMessage();
        }
   }

1 Comment

Thank you but as I answered Sahil as well, Thanks a lot but it doesn't really "catch" the exception: my POST request doesn't return the message but an exception: app.js:800 POST 127.0.0.1/memberform/changePassword 422 (Unprocessable Entity) app.js:Uncaught (in promise) Error: Request failed with status code 422 at createError –
1

Where are you returning the $error, you can return $error in view() or use redirect() or response() etc...

example:

return back()->back()->withError($error->getMessage())->withInput();

another example:

return response()->json('error_message' => $error->getMessage());

I hope you get the idea.

In blade view you can show $error message like this:

@if (session('error'))
    <div class="alert alert-danger" style="margin-top: 0.2rem;">
        {{ session('error') }}
    </div>
@endif

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.