Laravel 5 - global Blade view variable available in all templates

TemplatesLaravelViewLaravel 5Blade

Templates Problem Overview


How can I in Laravel 5 make global variable which will be available in all Blade templates?

Templates Solutions


Solution 1 - Templates

Option 1:

You can use view::share() like so:

<?php namespace App\Http\Controllers;

use View;

//You can create a BaseController:

class BaseController extends Controller {

    public $variable1 = "I am Data";

    public function __construct() {

       $variable2 = "I am Data 2";
       

       View::share ( 'variable1', $this->variable1 );
       View::share ( 'variable2', $variable2 );
       View::share ( 'variable3', 'I am Data 3' );
       View::share ( 'variable4', ['name'=>'Franky','address'=>'Mars'] );
    }  

}

class HomeController extends BaseController {

    //if you have a constructor in other controllers you need call constructor of parent controller (i.e. BaseController) like so:

    public function __construct(){
       parent::__construct();
    }

    public function Index(){
      //All variable will be available in views
      return view('home');
    }

}

Option 2: Use a composer:

  1. Create a composer file at app\Composers\HomeComposer.php

NB: create app\Composers if it does not exists

<?php namespace App\Composers;

class HomeComposer
{
    
    public function compose($view)
    {
        //Add your variables
        $view->with('variable1',      'I am Data')
             ->with('variable2',      'I am Data 2');
    }
}

Then you can attached the composer to any view by doing this

<?php namespace App\Http\Controllers;

use View;

class HomeController extends Controller{


    public function __construct(){
  
        View::composers([
            'App\Composers\HomeComposer'  => ['home'] //attaches HomeComposer to home.blade.php
        ]);

    }

    public function Index(){
        return view('home');
    }

}

Option 3: Add Composer to a Service Provider, In Laravel 5 I prefer having my composer in App\Providers\ViewServiceProvider

  1. Create a composer file at app\Composers\HomeComposer.php

  2. Add HomeComposer to App\Providers\ViewServiceProvider

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use View;
use App\Composers\HomeComposer;
use Illuminate\Support\Facades\Blade;

class ViewServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
 *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        //add to all views
        view()->composer('*', HomeComposer::class);
        //add to only home view 
        //view()->composer('home', HomeComposer::class);
    }
}

Solution 2 - Templates

Create a new Service Provider as suggested in here

Add your new Service Provider to the configuration file (config/app.php).

In the boot method of your new Service Provider use:

View::share( 'something_cool', 'this is a cool shared variable' );

Now you are ready to use $something_cool in all of your views.

Hope this helps.

Solution 3 - Templates

Searching for solution of the same problem and found the best solution in Laravel documentation. Just use View::share in AppServiceProvider like this:

View::share('key', 'value');

Details here.

Solution 4 - Templates

You can do this with view composers. View composers are executed when a template is loaded. You can pass in a Closure with additional functionality for that view. With view composers you can use wildcards. To make a view composer for every view just use a *.

View::composer('*', function($view)
{
    $view->with('variable','Test value');
});

You can also do this without a closure as you can see in the docs.

View::composer('*', 'App\Http\ViewComposers\ProfileComposer');

The profile composer class must have a compose method.

View composers are executed when a view is rendered. Laravel has also view creators. These are executed when a view is instantiated.

You can also choose to use a BaseController with a setupLayout method. Then every view which you will load is loaded through the setupLayout method which adds some additional data. However, by using view composers you're pretty sure that the code is executed. But with the BaseController approach you've more flexibility because you can skip the loading of the extra data.

EDIT: As mentioned by Nic Gutierrez you can also use view share.

Solution 5 - Templates

Also, you can do this in the Route.php file:

view()->share('variableName', $variable);

Solution 6 - Templates

I would rather use middleware with the view() facade helper. (Laravel 5.x)

Middleware is easier to mantain and does not make a mess in the controllers class tree.

Steps

Create the Middleware

/app/Http/Middleware/TimezoneReset.php

To create a middleware you can run php artisan make:middleware GlobalTimeConfig

share() the data you need shared

 <?php
    
    namespace App\Http\Middleware;
    
    use Closure;
    
    class GlobalTimeConfig
    {
        /**
         * Handle an incoming request.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Closure  $next
         * @return mixed
         */
        public function handle($request, Closure $next)
        {
            $time_settings = [
                'company_timezone' => 'UTC',
                'company_date_format' => 'Y-m-d H:i:s',
                'display_time' => true,
            ];
    
            view()->share('time_settings', $time_settings);
    
            return $next($request);
        }
    }
Register the newly created middleware

Add the middleware to your middleware route group as per example below

/app/Http/Kernel.php

    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\GlobalTimeConfig::class,
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            'throttle:60,1',
            'bindings',
        ],
    ];
Access data from templates

Access the data from any template with the given key in the View::share() method call

eg.:

    Company timezone: {{ $time_settings['company_timezone'] }}

EDIT: Nic Gutierrez's Service Provider answer might be a better (or the best) solution.

Solution 7 - Templates

and you can give array not just View::share('key', 'value'); can put array like View::share(['key'=>'value','key'=>'value'])

Solution 8 - Templates

You can add in Controller.php file:

use App\Category;

And then:

class Controller extends BaseController {
     public function __construct() {
        $categories = Category::All();
        \View::share('categories', $categories);
     }
}

Solution 9 - Templates

you can flash it into the session, you can define it in the .env file (static vars)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionLimon MonteView Question on Stackoverflow
Solution 1 - TemplatesEmeka MbahView Answer on Stackoverflow
Solution 2 - TemplatesNicolasView Answer on Stackoverflow
Solution 3 - Templatessha-1View Answer on Stackoverflow
Solution 4 - TemplatesArjanSchoutenView Answer on Stackoverflow
Solution 5 - TemplatesJodeveloper8View Answer on Stackoverflow
Solution 6 - TemplatesGabi DjView Answer on Stackoverflow
Solution 7 - TemplatesEhab ElzenyView Answer on Stackoverflow
Solution 8 - TemplatesArshad JilaniView Answer on Stackoverflow
Solution 9 - TemplatesJeffView Answer on Stackoverflow