32

So I'm following along with the Laravel 5 fundamentals tutorial and I am stuck on the form validation. I have followed along exactly with the tutorial but I am getting a Undefined variable: errors in my create articles view.

In the tutorial I am following and what I have found online they say the errors variable is always there in the blade file for you to use so I don't know what i am doing wrong?

Any help would be appreciated! loving Laravel except for this error!

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

Controller

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\User;
use App\Http\Requests;
use App\Http\Requests\UserRequest as UserRequest;
// use App\Http\Requests\CreateArticleRequest as CreateArticleRequest;
use App\Http\Controllers\Controller;
use Illuminate\View\Middleware\ErrorBinder;

class UserController extends Controller
{
    public function create(){
      return view('pages.signUp');
    }

    public function store(UserRequest $request){
      User::create($request->all());
      return 'the user has been registered!';
      return view('user.profile');
    }

}

Request validation

<?php

namespace App\Http\Requests;

use App\Http\Requests\Request;

class UserRequest extends Request
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'name' => 'required',
            'email' => 'required|email',
            'country' => 'required',
            'password' => 'required|min:6',
            'confirm_password' => 'required|same:password',
            'height' => 'required',
            'weight' => 'required',
        ];
    }
}
UnderDog
  • 305
  • 1
  • 4
  • 14
Neal Crowley
  • 331
  • 1
  • 3
  • 5

11 Answers11

41

This is a breaking problem with the 5.2 upgrade. What's happening is the middleware which is responsible for making that errors variable available to all your views is not being utilized because it was moved from the global middleware to the web middleware group.

There are two ways to fix this:

  1. In your kernel.php file, you can move the middleware \Illuminate\View\Middleware\ShareErrorsFromSession::class back to the protected $middleware property.

  2. You can wrap all your web routes with a route group and apply the web middleware to them.

    Route::group(['middleware' => 'web'], function() {
        // Place all your web routes here...
    });
    
smartrahat
  • 5,381
  • 6
  • 47
  • 68
user1669496
  • 32,176
  • 9
  • 73
  • 65
  • 1
    This is getting me most of the way there Thank you so much! It's been driving me crazy since yesterday! now I can see the error UL tag appear.. but the error messages aren't actually filling up? I went with the Route Option you suggested – Neal Crowley Dec 23 '15 at 16:39
  • And it's fully fixed now! put all of my routes that required validation into the route group you suggested and the foreach in my view need $errors->all() Thank you so much! – Neal Crowley Dec 23 '15 at 16:43
  • What did you need to do to get the errors variable to fill up so I can modify the answer? – user1669496 Dec 23 '15 at 16:46
  • I'm following the [Intermediate Tutorial](https://laravel.com/docs/5.2/quickstart-intermediate) and having this problem with **ALL** the auth routes. The instructions in that page are incorrect (or perhaps incompleted). The best solution to the problem is #2 above. – Kryten Jan 11 '16 at 15:20
  • `Route::auth()` is actually by default called in a `Route::group(['middleware' => 'web']`... so this just suggests doing the default... which doesn't actually seem to want to help..? – Dan Dart Mar 27 '16 at 22:10
  • Thanks for this post. I already did option 2, but decided to do the opposite and move my route out of the middleware, and then it worked. I decided to follow the advice below and make the needed changes to my Kernel.php file. – Richard Chassereau May 05 '16 at 20:18
24

Solved

You may change any one of the following:

1. put your working route (app/http/routes.php) on

Route::group(['middleware' => ['web']], function () { // Here like Route::get('/', 'TodoController@index'); Route::post('/', 'TodoController@store'); });

Screenshot -

Screendshot 1

2. Move your protected $middlewareGroups web (app/Http/Kernel.php) on protected $middleware = []

Screenshot -

screenshot2

Manoj Salvi
  • 2,639
  • 1
  • 17
  • 21
  • 1
    Thanks. This worked for me. Why aren't the middlewareGroups needed for validation in the kernel available by default? – Richard Chassereau May 05 '16 at 20:21
  • This works for me. Btw, I didnt like option of moving middleware group to global but I wanted to add two middleware for admin url. "web" and "admin". As they say, web is automatically add by routeserviceprovider so If I add only admin then it doesnt take any other middleware assigned for web so I have to give both option like Route::group(['middleware' => ['web','admin'], 'prefix' => 'admin'], function () { ... and this doesnt work as web included two times. Laravel team should fix this asap; – Chetan Patel Jun 14 '16 at 13:35
  • sweet thats what wecall an answer :) – vimuth Oct 10 '16 at 15:30
  • Superb....... it's working perfect for me..... you save my lot's of time – Nitin Vaghani Feb 06 '17 at 07:32
19

This is solution:

Change the defination of your Route groups with a middleware, from :

Route::group(['middleware' => 'web'], function () {

to

Route::group(['middlewareGroups' => 'web'], function () {

Source: https://github.com/laravel/framework/issues/13000

MD Ashik
  • 9,117
  • 10
  • 52
  • 59
Yuri
  • 191
  • 2
  • 4
  • None of the above worked for me (except modify the Kernel.php file, but I don't like this solutions for many stuff), but this solution fix my problem. I have many nested Route:group in my routes.php file and I am using Route:resource too – manuelpgs Jul 18 '16 at 22:35
  • Here and now in 2017, this is the solution to this problem. Thanks a lot @Yuri – Kenshinman Apr 13 '17 at 12:09
18

simply, you have to move :

\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,

from protected $middlewareGroups to protected $middleware

7
  1. Just remove , 'middleware' => 'web' from Route::group(array('prefix' => 'user', 'middleware' => 'web'), function() in routes.php page OR

  2. Move

    \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class,

From protected $middlewareGroups to protected $middleware in kernel.php page

As the Laravel Documentation says:

Note: If your copy of Laravel has a RouteServiceProvider that already includes the default routes file within the web middleware group, you do not need to manually add the group to your routes.php file.

So removing from routes.php file would be the correct way.

thechaoticpanda
  • 396
  • 2
  • 18
Atiqur
  • 3,802
  • 1
  • 25
  • 26
5

Posting this as it might be useful for others,

As Smartrahat mentioned in 1st solution, in your Kernel.php file(app/Http/Kernel.php) move \Illuminate\View\Middleware\ShareErrorsFromSession::class from $middlewareGroups to protected $middleware property, but the same will start throwing the error "Session store not set on request",

to resolve this move \Illuminate\Session\Middleware\StartSession::class, to $middleware property as well.

Kumar Sambhav Pandey
  • 1,713
  • 4
  • 22
  • 33
4

As of 5.2, routes.php is by default already called in the context of a ['middleware'=>'web'] by RouteServiceProvider. But in routes.php default generation of auth routes, the Route::group call is still happening by default - so if you delete that Route::group declaration from routes.php the application then correctly shows errors.

Dan Dart
  • 342
  • 3
  • 13
4

A couple of observations regarding this issue. First off there a related bug in github regarding this issue PFA https://github.com/laravel/framework/issues/12022

If you look at the last comment which Graham wrote, I think that is the facing I was facing. For me even though there was a error in form post data, I was getting the below equality

boolval(count($errors) === 0) === true

In my case I added log statements in the

\Illuminate\Session\Middleware\StartSession::class

the above middleware class ran twice for a given request, I am not sure why it ran twice, but I think because of this the $errors variable is getting reset. I was using this configuration (which I think came default with Laravel@5.2.43)

protected $middleware = [
    \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
];

protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
    ],

    'api' => [
        'throttle:60,1',
    ],
];

protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'can' => \Illuminate\Foundation\Http\Middleware\Authorize::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
];

I changed the configuration which worked for me and the $errors variable's count is not zero (also the above middleware ran only once per request)

protected $middleware = [
    \Illuminate\Session\Middleware\StartSession::class,
    \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
];

protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
    ],

    'api' => [
        'throttle:60,1',
    ],
];

protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'can' => \Illuminate\Foundation\Http\Middleware\Authorize::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
];

Note: All my routes are in the web middleware group before and after the Kernel.php configuration change, I didnot move my routes at all from the web middleware group.

agent47
  • 181
  • 2
  • 9
2

Change @foreach($errors->any() as $error) to @foreach($errors->all() as $error)

smartrahat
  • 5,381
  • 6
  • 47
  • 68
  • Still getting the same error Undefined variable: errors And i am now following the docs with regards to the form validation linked here: https://laravel.com/docs/5.2/validation – Neal Crowley Dec 23 '15 at 16:23
0

in this case laravel 5.2 you can refer may example code and edit your kernal.php file. move this \Illuminate\View\Middleware\ShareErrorsFromSession::class, form middlewareGroups to middleware and add \Illuminate\Session\Middleware\StartSession::class, to middleware then its work correctly.

MD Ashik
  • 9,117
  • 10
  • 52
  • 59
Madhuka Dilhan
  • 1,396
  • 1
  • 14
  • 21
0

Having both Web and API requirements in our application, we did not want to move the middleware around; perhaps that would have worked, however:

We had the very peculiar situation that the flash[] and $errors session data was transmitted correctly between the standard laravel resource methods, store() and edit(), but in some cases the data did not get back across nearly identical methods, storeSale() and editSale().

We found that in our development and deployment environments, the 'file' and 'database' session drivers worked in all cases, but the 'cookie' driver did not.

Switching to the database driver in all instances solved the problem.

Paul Roub
  • 36,322
  • 27
  • 84
  • 93
JDA3
  • 356
  • 3
  • 7