13

After I upgraded to Laravel 5.2 I encountered a problem with the laravel validator. When I want to validate data in a controller take for example this code.

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;

class ContactController extends Controller
{
    public function storeContactRequest(Request $request)
    {
        $this->validate($request, [
            '_token' => 'required',
            'firstname' => 'required|string'
            'lastname' => 'required|string'
            'age' => 'required|integer',
            'message' => 'required|string'
        ]);

        // Here to store the message.
    }
}

But somehow when I enter unvalid data it will not redirect me back to the previous page and flash some messages to the session but it will trigger an exception and gives me a 500 error page back.

This is the exception I get. I have read in the documentation that the ValidationException is new instead of the HttpResponseException but I don't know if it has anything to do with this.

[2016-01-05 11:49:49] production.ERROR: exception 'Illuminate\Foundation\Validation\ValidationException' with message 'The given data failed to pass validation.' in /home/vagrant/Code/twentyre-webshop/vendor/laravel/framework/src/Illuminate/Foundation/Validation/ValidatesRequests.php:70

And when I use a seperate request class it will just redirect back with the error messages. It seems to me only the validate method used in a controller is affected by this behaviour.

xAoc
  • 3,018
  • 3
  • 18
  • 33
DB93
  • 600
  • 1
  • 4
  • 16
  • 3
    This is by design. Request classes do the redirect, if you validate manually using ValidatesRequests trait and validate() method you need to catch the exception and handle that yourself. – jedrzej.kurylo Jan 05 '16 at 12:02
  • But how do I catch the exception when I use it like this in a controller? – DB93 Jan 05 '16 at 12:12
  • 1
    Wrap it in try/catch clause – jedrzej.kurylo Jan 05 '16 at 12:18
  • Thanks I fixed it I didn't know it was on purpose that it didn't redirect automatically. – DB93 Jan 05 '16 at 12:22
  • @DB93 How did U solve it? Where did you do redirect? – Yurich Jul 06 '16 at 18:49
  • @Yurich I did wrap it in a try/catch clause and I redirected in the catch – DB93 Jul 20 '16 at 09:13
  • This is definitely NOT how it is explained in the doc: `The validate method accepts an incoming HTTP request and a set of validation rules. If the validation rules pass, your code will keep executing normally; however, if validation fails, an exception will be thrown and the proper error response will automatically be sent back to the user. In the case of a traditional HTTP request, a redirect response will be generated, while a JSON response will be sent for AJAX requests.` – Ben Dubuisson Feb 17 '18 at 21:37

7 Answers7

3

Update your App\Exceptions\Handler class

use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Illuminate\Foundation\Validation\ValidationException;

/**
 * A list of the exception types that should not be reported.
 *
 * @var array
 */
protected $dontReport = [
    AuthorizationException::class,
    HttpException::class,
    ModelNotFoundException::class,
    ValidationException::class,
];

I also recommend you to read the docs how to migrate to laravel 5.2, because there were some breaking changes. For example this, ValidatesRequests trait throws Illuminate\Foundation\Validation\ValidationException instead of Illuminate\Http\Exception\HttpResponseException

Documentation how to migrate from Laravel 5.1 to 5.2

xAoc
  • 3,018
  • 3
  • 18
  • 33
  • 1
    This won't give the OP the result they need - it won't redirect to previous page and flash validation errors. – jedrzej.kurylo Jan 05 '16 at 12:05
  • 1
    I did add the ValidationException to the dontReport property but it didn't fix my problem. I have read the migration documents and applied all the changes to my project but this is the only thing that is failing for me. – DB93 Jan 05 '16 at 12:10
3

Example from laravel docs. You can use Validator facade, for custom validation fails behaviour

public function store(Request $request)
{
    $validator = Validator::make($request->all(), [
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ]);

    if ($validator->fails()) {
        return redirect('post/create')
                    ->withErrors($validator)
                    ->withInput();
    }

    // Store the blog post...
}
Nickstery
  • 116
  • 4
1

This is how I handle it in Laravel 5.3 (by modifying Handler.php)

https://stackoverflow.com/a/42852358/3107185

Community
  • 1
  • 1
Rav
  • 1,391
  • 1
  • 15
  • 28
1

For laravel 5.2 I had to add this line:

    if ($e instanceof ValidationException) 
    {
         return redirect()->back()->withInput();
    }

In App\Exceptions\Handler.php,and the following headers:

    use Illuminate\Session\TokenMismatchException;
    use Illuminate\Database\Eloquent\ModelNotFoundException;
    use Symfony\Component\HttpKernel\Exception\HttpException;
    use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
    use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
    use Illuminate\Validation\ValidationException;
    use Illuminate\Auth\AuthenticationException;
0

For my purpose, I was bulding a fully API based application in Laravel 5.3 which I had manually upgraded from Laravel 5.1. and I just needed Laravel to respond back with the validation errors that needed fixing on my FormRequest.

Adding this line:

elseif ($e instanceof ValidationException) 
 {
        return $this->convertValidationExceptionToResponse($e, $request);
 }

after this one:

    if ($e instanceof ModelNotFoundException) {
        $e = new NotFoundHttpException($e->getMessage(), $e);
    }

In App\Exceptions\Handler.php did the trick for me and returned expected validation errors when using FormRequest validation.

Please see my comments here: @ratatatKE's comments on github

Moses Ndeda
  • 383
  • 4
  • 11
0

might save someone time, Another issue is that you are calling validator->validate() in the view, not in the controller

i was calling in the view because i have a lazy load component that triggered on the view

david valentino
  • 783
  • 9
  • 16
-4

I had the same problem when upgrading 4.2 to 5.3.

This answer worked for me.

Override the method in app/Exceptions/Handler.php

protected function convertExceptionToResponse(Exception $e)
{
    if (config('app.debug')) {
        $whoops = new \Whoops\Run;
        $whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler);

        return response()->make(
            $whoops->handleException($e),
            method_exists($e, 'getStatusCode') ? $e->getStatusCode() : 500,
            method_exists($e, 'getHeaders') ? $e->getHeaders() : []
        );
    }

    return parent::convertExceptionToResponse($e);
}

Answer found here: https://laracasts.com/discuss/channels/laravel/whoops-20-laravel-52

Robbie
  • 562
  • 1
  • 5
  • 12
  • This has nothing to do with the question. – brad Sep 21 '16 at 21:36
  • I had the same problem as the question. "Laravel validator throws an exception instead of redirecting back". That's the problem I was having. I fixed it with the solution above. There might be more than one cause for this error therefore more than one answer. I posted to help someone who is struggling with this error like I was. – Robbie Sep 23 '16 at 11:50