2

I am trying to get validation errors to show up in Laravel.

I have a UserController set up like so:

<?php

namespace App\Http\Controllers;

use App\User;
use App\Http\Controllers\Controller;
//Use Request;
Use Flash;
Use Illuminate\Http\Request;

class UserController extends Controller
{
    /**
     * Show the profile for the given user.
     *
     * @param  int  $id
     * @return Response
     */
    public function showProfile($id)
    {
        return view('user.profile', ['user' => User::findOrFail($id)]);
    }

    public function store(Request $request) {
        $this->validate($request, [
            'email' => 'required|unique:users|email|max:255',
        ]);

        if($this) {

        $input = Request::all();

        User::create($input);

        return redirect('/');

        }
        else {

            return redirect('/')->withErrors($validator);
        }
    }
}

In my view (layout.blade.php), I have included:

@if (count($errors) > 0)
@foreach ($errors->all() as $error)
   {{!! $errors !!}}
@endforeach
@endif

To account for the route, I have:

Route::group(['middleware' => ['web']], function () {
    Route::get('/', function (){
        return view('home');
    });
});

Unfortunately, when I enter "bad" data that shouldn't be verified, I am not seeing any error (but it is not being stored in the db, so there's that).

One other note, when the blade template is rendered, I am seeing an extra "}" bracket, which I'm not sure why that is there.

halfer
  • 19,824
  • 17
  • 99
  • 186
user1072337
  • 12,615
  • 37
  • 116
  • 195

6 Answers6

17

In laravel version 5.2.41, the middleware web is thrown out.

Means adding the routes inside Route::group(['middleware' => ['web']], function () { will make the validation not work.

Box Box Box Box
  • 5,094
  • 10
  • 49
  • 67
Mirza Vu
  • 1,532
  • 20
  • 30
  • 3
    OMG! I spent almost an hour trying to figure this out until I wrote your message. It is completely true! I am following a tutorial that is a few months old and they still use the 'middleware web' which I found funny because when I created my Laravel project, such thing wasn't on the route.php file. I just removed it and put it back the way it was and I am able to read my errors now. Thanks! – Manu Gtez Oct 06 '16 at 19:19
  • Same happened for me. Spent 2 hours figuring out myself :) – Mirza Vu Oct 07 '16 at 11:13
7

There are a couple things wrong or that can be improved here. The store method on the UserController has a lot of weird issues. $this will always be true because objects are true in php. Also, you pass in $validator into withErrors which doesn't make sense because there's no variable validator.

public function store(Request $request) {
    $this->validate($request, [
        'email' => 'required|unique:users|email|max:255',
    ]);

    User::create(Request::all());
    return redirect('/');
}

The validate method will throw an Illuminate\Foundation\Validation\ValidationException if there is a validation error. This exception should be listed in the $dontReport instance variable in App\Exceptions\Handler as seen below:

protected $dontReport = [
    AuthorizationException::class,
    HttpException::class,
    ModelNotFoundException::class,
    ValidationException::class,
];

If you have changed these values, removed, or modified the ValidatesRequest trait you may have broken this functionality.

Your error reporting code is not correct either:

@foreach ($errors->all() as $error)
   {!! $errors->first() !!}
@endforeach

There are 3 changes here. First I removed the outer errors size check, this doesn't really get you anything. Next, I fixed your extra } error, the syntax for un-escaping data is {!! $errors->first() !!}. Lastly, I called ->first() this returns the first error associated with that particular field.

I think it's important to note that the validation exception will create a redirect response to the previous page. The logic for determining the previous page can be found in Illuminate\Routing\UrlGenerator::previous().

Logan Bailey
  • 7,039
  • 7
  • 36
  • 44
0

The errors block should be:

@if (count($errors) > 0)
    <div class="alert alert-danger">
        <ul>
        @foreach ($errors->all() as $error)
            <li>{{ $error }}</li>
        @endforeach
        </ul>
    </div>
@endif

Assuming you're using Bootstrap for the alerts.

You also don't have $validator defined. You need to do something like this:

$validator = Validator::make($request->all(), [
    'email' => 'required|unique:users|email|max:255',
]);

Instead of $this->validate().

That should do it.

Logan Bailey
  • 7,039
  • 7
  • 36
  • 44
Chris
  • 3,729
  • 22
  • 30
  • 1
    controllers have a validate method that throws an exception, you dont have to change to making a validator yourself. – lagbox Jan 20 '16 at 01:39
0

If it is still not working and you have tried several things like

  1. Moving ShareErrorsFromSession::class from $middlewareGroups to $middleware
  1. Removing the web.php to web middleware

Try modifying the request headers to

Accept: application/json

Or you can also create a new middleware that will modify the request header like this:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class ModifyAcceptHeaderMiddleware
{
    public function handle(Request $request, Closure $next)
    {
        $request->headers->set('Accept', 'application/json');

        return $next($request);
    }
}

Player1
  • 2,878
  • 2
  • 26
  • 38
0

Try to remove "\Illuminate\Session\Middleware\StartSession::class" from 'middleware' in Kernel.php, it must be only in the 'web' group.

-1
@if(count(($errors->all()) > 0))
@foreach($errors->all() as $error)
    <div class="alert alert-danger">
        {{$error}}
    </div>
@endforeach
@endif