Override section in a laravel blade template throwing undefined variable errors
Asked Answered
G

6

6

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?

Gape answered 15/10, 2013 at 10:36 Comment(0)
I
10

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.)

Implication answered 15/10, 2013 at 14:42 Comment(0)
B
2

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 @extending.

E.g. 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.

E.g. 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])
Bowes answered 25/10, 2017 at 15:49 Comment(0)
N
2

In your page try this:

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

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

Nork answered 30/10, 2021 at 23:23 Comment(0)
C
1

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

Conciliatory answered 15/10, 2013 at 11:28 Comment(1)
It is entirely intentional. Blade layouts must always render a parent prior to a child or inheritance would not be possible.Implication
C
0

I used this blade:

in layouts\app.blade.php

@section('footer')
    <footer-component></footer-component>
@show

then in custom.blade.php

@extends('layouts.app')

@section('footer')
    your custom blade.php goes here
@endsection
Couvade answered 5/5, 2023 at 22:58 Comment(0)
A
-5

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!

Adrianadriana answered 16/4, 2015 at 20:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.