How can I straighten out Laravel blade @extends or

2019-06-21 16:24发布

问题:

In my attempts to find a way to pass a variable by reference to a blade @include, I built a simple test case which also demonstrates that the template order of execution is quite volatile. Is there a way to use blade templates with a variable where the order of execution matters (specifically with regard to sections)?

Test Case:

testLayout.blade.php

<!DOCTYPE html>
<html>
<head>
</head>
<body>
{{"this is the layout: ".++$tabindex."<br>"}}
@include('testInclude')
{{"this is the layout after include: ".++$tabindex."<br>"}}
@include('testInclude',array('tabindex'=>$tabindex))
{{"this is the layout after passing include: ".++$tabindex."<br>"}}
@yield('testYield')
{{"this is the layout after yield: ".++$tabindex."<br>"}}
@section('testSection')
{{"this is the layout section: ".++$tabindex."<br>"}}
@show
{{"this is the layout after section: ".++$tabindex."<br>"}}
</body>
</html>

testExtension.blade.php

@extends('testLayout')
{{"this is the extension: ".++$tabindex."<br>"}}
@include('testInclude')
{{"this is the extension after include: ".++$tabindex."<br>"}}
@include('testInclude',array('tabindex'=>$tabindex))
{{"this is the extension after passing include: ".++$tabindex."<br>"}}
@section('testYield')
{{"this is the extension yield: ".++$tabindex."<br>"}}
@stop
{{"this is the extension after yield: ".++$tabindex."<br>"}}
@section('testSection')
{{"this is the extension section: ".++$tabindex."<br>"}}
@parent
{{"this is the extension section after parent: ".++$tabindex."<br>"}}
@stop
{{"this is the extension after section: ".++$tabindex."<br>"}}

testInclude.blade.php

{{"this is the include: ".++$tabindex."<br>"}}

routes.php

Route::get('test', function(){
    return View::make('testExtension',array('tabindex'=>0));
}); //I have used View::share in stead and the results are identical

Output:

this is the extension: 1
this is the include: 2
this is the extension after include: 2
this is the include: 3
this is the extension after passing include: 3
this is the extension after yield: 5
this is the extension after section: 8
this is the layout: 9
this is the include: 10
this is the layout after include: 10
this is the include: 11
this is the layout after passing include: 11
this is the extension yield: 4
this is the layout after yield: 12
this is the extension section: 6
this is the layout section: 13
this is the extension section after parent: 7
this is the layout after section: 14

Analysis:

It would appear that the values are calculated in the extension and then calculated in the layout and then re-ordered. Because it's already another separate question, please ignore that all @include instances are pass-by-value and thus do not affect the value in their including files. I'm also generally less concerned about values outside of sections because the behavior there is understandably less predictable. This is problematic in sections.

If the layout does anything with a value, the value will be calculated after all the extension values are calculated and this is problematic because the order of execution is decidedly not mimicking the output order. To get the values behaving as they should, I could @overwrite all applicable cases in every extension, defeating the point of using templates in the first place, but, in that case, I'd be just as well off to define each view without any such extension at all.

Is there any way to get the sections to behave in-order or can I really only use templates for things where values are order-independent?

回答1:

Templates are order-independent. Sections can be overwritten using @overwrite, which means they are rendered when everything is loaded, otherwise @overwrite could fail.


Overwriting Sections

By default, sections are appended to any previous content that exists in the section. To overwrite a section entirely, you may use the overwrite statement:

@extends('list.item.container')

@section('list.item.content')
    <p>This is an item of type {{ $item->type }}</p>
@overwrite

http://laravel.com/docs/templates