Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

laravel blade, how to append to a section

If you look to laravel official documentation http://laravel.com/docs/4.2/templates It says that giving this layout:

<!-- Stored in app/views/layouts/master.blade.php -->  <html>     <body>         @section('sidebar')             This is the master sidebar.         @show          <div class="container">             @yield('content')         </div>     </body> </html> 

Extended by this view

@extends('layouts.master')  @section('sidebar')       <p>This is appended to the master sidebar.</p> @stop  @section('content')     <p>This is my body content.</p> @stop 

Will append to the section sidebar. But actually if you try is it doesn't append, it just override the content from the extended template.

I heard about others blade function like @append, @prepend, @parent... no one seems to work.

Beside, this example in the official doc which doesn't work, I find that the blade documentation is very poor. There's nothing about blade function like @parent for instance.

like image 240
Amaynut Avatar asked Oct 28 '14 18:10

Amaynut


2 Answers

The example in the documentation from Laravel website does indeed seem to be flawed, but I think it's a markdown parsing problem on the website, the same docs on github show the correct code:

In any case @parent does indeed work. The example in the docs should look like this:

@extends('layouts.master')  @section('sidebar')     @parent      <p>This is appended to the master sidebar.</p> @stop  @section('content')     <p>This is my body content.</p> @stop 

A quick look in the Illuminate/View/Factory.php confirms what @parent does:

/**  * Append content to a given section.  *  * @param  string  $section  * @param  string  $content  * @return void  */ protected function extendSection($section, $content) {     if (isset($this->sections[$section]))     {         $content = str_replace('@parent', $content, $this->sections[$section]);     }      $this->sections[$section] = $content; } 
like image 105
Bogdan Avatar answered Sep 19 '22 17:09

Bogdan


You can simply use @append...

@extends('layouts.master')  @section('sidebar')     <p>This is appended to the master sidebar.</p> @append  @section('content')     <p>This is my body content.</p> @stop 

See here.

To understand how this works...

The compileStatements() method in the BladeCompiler calls the method compileAppend(), as you can see here:

/**  * Compile Blade Statements that start with "@"  *  * @param  string  $value  * @return mixed  */ protected function compileStatements($value) {     $callback = function($match)     {         if (method_exists($this, $method = 'compile'.ucfirst($match[1])))         {             $match[0] = $this->$method(array_get($match, 3));         }          return isset($match[3]) ? $match[0] : $match[0].$match[2];     };      return preg_replace_callback('/\B@(\w+)([ \t]*)(\( ( (?>[^()]+) | (?3) )* \))?/x', $callback, $value); } 

In turn, that inserts a call to appendSection() which looks like this:

/**  * Stop injecting content into a section and append it.  *  * @return string  */ public function appendSection() {     $last = array_pop($this->sectionStack);      if (isset($this->sections[$last]))     {         $this->sections[$last] .= ob_get_clean();     }     else     {         $this->sections[$last] = ob_get_clean();     }      return $last; } 
like image 40
user1960364 Avatar answered Sep 18 '22 17:09

user1960364