简体   繁体   中英

Override section in a laravel blade template throwing undefined variable errors

I am using Laravel 4 and blade templates, and running into an issue when I try and extend a template.

In my layout I have

@yield('content')

and in my page I have

@section('content')
    Welcome {{ $name }}
@stop

which works fine, I've created another page very similar to my first, and just want to change override the admin content section. The other sections in the template are fine.

so I extend my page, and do

@section('content')
    Hello!
@stop

I get an undefined notice with the $name variable.

I tried

@section('content')
    Hello!
@overwrite

and same deal, I get the notice error. I checked my controller and it IS using the correct template. I am not calling @parent so I don't understand, how can I overwrite a section in a template with out notice errors?

Blade layouts work their way up the tree to the route or master view before rendering any of the children. Thus, nested views that extend others must always have their parent rendered before they are. As a result, parent views that contain sections will always be rendered prior to the child.

To overcome the problem you are experiencing it is a good idea to only ever nest pages that don't overwrite parents sections that contain variables, as the parents content will always be rendered before the child.

As the above ideal can't always be adhered to or a parents section content is still required, a good alternative method would be to use view composers. View composers give you an opportunity to declare variables for any specific view whenever they are rendered.

View::composer(array('pages.admin'), function($view)
{
    $view->with('name', Auth::user()->username);
});

Another alternative would be to use a view creator. Creators are fired the moment a view is instantiated rather than rendered. This method allows you to overwrite the variable should you so wish prior to the view being rendered.

View::creator(array('pages.admin'), function($view)
{
    $view->with('name', Auth::user()->username);
});

You can read up more about these methods in the documentation here . (Or here for the Laravel 5 documentation.)

I am not sure if this is a bug or intentional, but it seems like Laravel renders the variables before interpreting blade instructions. The workaround would be this:

views/layouts/testlayout.blade.php:

    <html>
    <body>
        @yield('sidebar', 'This is the master sidebar. {{ $name }}' )

        <div class="container">
            @yield('content')
        </div>
    </body>
   </html>

actual view: views/test.blade.php

@extends('layouts.testlayout')


@section('sidebar')
   No variable in the child
@stop

@section('content')
    This is a child content
@stop

This prevents the variable $name to get rendered if there is a section with that name in the actual view. It seems like this is the approach if the content in the layout file contains a variable

I can't guarantee support for Laravel 4 but for those looking for a solution that works in Laravel 5.5 (and probably a fair bit further back – hard to check) is to define the variables you need when @extend ing.

Eg in the example in the question:

@extend('my.parent.view', ['name' => ''])

This approach can be especially useful if the data needed is available to the child-view, but under a different name.

Eg if a parent-view needed a $parent variable, but the child view only has a $child variable which has a property referencing the parent, you might do:

@extend('my.parent.view', ['parent' => $child->parent])

In your page try this :

@section('content')
    @hasSection('content')
        @yield('content')
    @else
        Welcome {{ $name }}
    @endif
@stop

And read this post for more inspiration https://laracasts.com/discuss/channels/laravel/laravel-blade-layouts-inheritence-problem

I found an easy solution for this problem :)

Just add the @ symbol before the variable/method you call in the parent view. If there is an error (notice/warning) PHP will ignore that and continue the execution.

It's not perfect, but save us to code view/composers.

Hope this help!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM