6

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?

Community
  • 1
  • 1
skovacs1
  • 461
  • 1
  • 6
  • 14

1 Answers1

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

gidomanders
  • 465
  • 5
  • 16
  • +1 But... Could you format your answer, like *** (horizontal line) instead of ==== and use the code block for highlighting code. thx! – toesslab Sep 03 '14 at 08:50
  • I appreciate the effort (and indicating a typo (@override should have been @overwrite)). This doesn't answer the yes/no question. My tests showed that templates are order-independent. I said in my analysis that I could @overwrite in every single extension to get ordered values where I need them (defeating the point of templating by redefining the entire page). If you can definitively confirm there is no way to template with order being preserved, could you add that to the answer? A reference to where in the source this is happening would be proof enough and would be a start to resolving this. – skovacs1 Sep 03 '14 at 17:34
  • 1
    Also, I have a strong suspicion this is actually a problem from Symphony where this templating engine originates to my knowledge. – skovacs1 Sep 03 '14 at 17:37