Laravel扩展刀片模板 - $ errors集合中的错误

I am using Laravel 5.3. My first Laravel project/learning experience In my blade file I use the following snippet to show the errors below a field after a PUT or POST request.

In this case the database field is called firstName

        @if ($errors->has('firstName'))
            <span class="help-block">
                <strong>{{ $errors->first('firstName') }}</strong>
            </span>
        @endif

Now since I have lot of fields, I have keep repeatings this block for every field. I looked up the Laravel docs on Blade templates (Extending Blade section) and thought I could do the following in the AppServiceProvider class (AppServiceProvider .php)

public function boot()
{
    //
    Blade::directive('showIfError', function($fieldName) {
        if ($errors->has('$fieldName')) {
            echo "<span class='help-block'>
            <strong> $errors->first('$fieldName') </strong>
            </span>";
        }
    });
}

and then use

@showIfError('firstName')

But no luck...I get the error 'Undefined variable: errors'

Looks like the Laravel error collection is not accessible in this view file.

Appreciate any help. Thanks.

The thing is $errors in not accessible in closure. Also, you can't pass whole object as directive closure accepts string only. With simple data you can implode() and then explode() it, but not with an object or a collection.

What you can do is to create $errors manually inside the closure.

I've tested it and it works as expected:

Blade::directive('showIfError', function($fieldName) {
    $errors = session('errors');

    if ($errors->has($fieldName)) {
        return "<span class='help-block'>".$errors->first($fieldName)."</span>";
    }
});

The issue is that the $errors variable is only available within the views. If you take a look at the Middleware that shares the variable (https://github.com/laravel/framework/blob/5.0/src/Illuminate/View/Middleware/ShareErrorsFromSession.php) you will see that it is stored in the session.

So you can access it as follows:

$errors = session()->get('errors');

Note in your example you do have a couple of other issues; the $fieldName variable should not be in quotes. Eg:

public function boot() {
Blade::directive('showIfError', function($fieldName) {
$errors = session()->get('errors');
 if ($errors->has($fieldName)) {
      echo "<span class='help-block'> <strong>". $errors->first($fieldName). "</strong> </span>";
 } 
});
}

I finally wrote a PHP function inside my view and call it with various field names. I hope this is a good approach. Not sure what is the best way to implement this.

function showIfError($fieldName)
{
    $errors=session('errors');
    if ( count( $errors)>0) {
        if (session('errors')->has($fieldName)) {
            $msg=$errors->first($fieldName);
            echo '<span class="help-block">
                    <strong>'. $msg.' </strong>
                </span>';
        }
    }

}

This is late reply, but hopefully it will help another person who comes along. A custom blade directive is supposed to return a string php code that will be evaluated when the template is rendered. Because the $errors variable is only available when the response is made, it won't work trying to evaluate it in the directive. The solution is this :

 // custom blade directive to render the error block if input has error
 // put this inside your service provider's boot method

     \Blade::directive('errorBlock', function ($input) {
            return
                '<?php if($errors->has('.$input.')):?>
                    <div class=\'form-control-feedback\'>
                        <i class=\'icon-cancel-circle2\'></i>
                    </div>
                    <span class=\'help-block\'>
                            <strong><?php echo $errors->first('.$input.') ?></strong>
                    </span>
                 <?php endif;?>';
        });