Laravel View Composer options not available in layout extensions

I am using the Laravel view composer to share a pair of variables with all views.

app/composers.php :

 View::composer('layouts.base', 'MyApp\Composers\BaseComposer'); 

My understanding here is that everything layouts.base uses will get the data of the composer of the view.

BaseComposer@compose , simplified:

  public function compose($view) { // Some logic left out here that pulls in some data $data = array( 'name' => 'John', 'status' => 'active' ); $data = (object) $data; return $view->with('global', $data); } 

Given this layouts.base :

  {{ $global->name }} @include('layouts.partials.header') @yield('content') 

$global->name , and this also applies to the included layouts.partials.header :

  {{ $global->status }} 

But a view extending layouts.base raises an Undefined variable: global error:

home.blade.php

 @extends('layouts.base') @section('content') {{ $global->name }} @stop 

Everything works fine if I change composers.php to the home link:

 View::composer(['layouts.base', 'home'], 'MyApp\Composers\BaseComposer'); 

I would like to understand why, if home extends layouts.base , it cannot see view linker variables without this extra step.

+8
php laravel laravel-4
source share
1 answer

The problem here is how it all happens. The composer view is called before the corresponding view is displayed. This means in your case:

  • view home gets rendered
  • composer view for layouts.base called
  • view layouts.base gets rendered

This causes the global variable to be unavailable in the home view.

Here are some solutions that may help.

Change composer template

Modify the composer matching pattern to include all the views that need the variable. Use a wildcard * if possible.
You can even map each view:

 View::composer('*', 'MyApp\Composers\BaseComposer'); 

Do not use composers at all

If you need your data (almost) for each view, you can use View::share at application startup time.

Put this in app/filters.php , app/start/global.php or a similar file

 $data = array( 'name' => 'John', 'status' => 'active' ); $data = (object) $data; View::share('global', $data); 

Rethinking

Why do different views need the same global data? Could you move the part of the view that needs data to the partial view that you can include?

+7
source share

All Articles