PHP

Laravel

Published: 1 year ago Updated: 3 months ago 1752

There are two approaches to sharing data across  views  in Laravel, view share and view composer. In this tuts I will give you a brief overview of both of them  and more importantly what you should be careful about when using composer. Now, let's dive in.

View Share

View share runs before the view object is created and is a key/value storage, just like Session::put(), you put your data under a specific key and you will get a same named variable across your views, a straight forward approach, nothing more needs to be said about it.

<?php 

view()->share('key', $value)

Now how would you use it in your application? Well, a common approach is to create a MasterController which all of your controllers will extend instead of the Laravel's Controller class. Or you can extract the logic you need to get your data in a Trait if you prefer that approach over inheritance.

<?php

namespace App\Http\Controllers;


class MasterController extends Controller
{
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->share('some_key', $this->getData());
    }

    protected function getData()
    {
        //Your awesome logic e.g.
        return DB::tables('some_table')->get();
    }

    protected function share($key, $data)
    {
        view($key, $data); 
    }
}

View Composer

View composer on the other hand runs after the view object has been created and allows us for more flexibility, you register a callback, either an anonymous function or a class to be executed across multiple views, but there is a catch to this and you need to be careful about it, you need to know that callable will be executed for every view, that means all the sections of content you yield or all those partials you include will also trigger this callback.

<?php

/* Share data across all views */
view()->composer('*', function($view) {
    //your awesome logic 
    $view->with($data);
});

/* Share data across multiple views */
view()->composer(['home.index', 'dashboard.*', 'blog.post'], function($view) {
   //do something awesome here as well
   $view->with($data);
});

/* Share data using a custom class */
view->composer('*', AwesomeViewComposer::class);

So how do we circumvent this duplicating queries issue? It's really simple, all we need is to create our ViewComposer::class. 

<?php 

use Illuminate\Contracts\View\View;

class ViewComposer {

  protected $data;

  /**
   * Create a new ViewComposer instance.
   */
  public function __construct()
  {
    $this->data = 'Your data';
  }

  /**
   * Compose the view.
   *
   * @return void
   */
  public function compose(View $view)
  {
    $view->with('shared_data', $this->data);
  }

}

And register it as a singleton, in either the AppServiceProvider or our custom ViewComposerServiceProvider.

<?php

namespace App\Providers;

use App\Channel;
use Illuminate\Support\ServiceProvider;
use Illuminate\Contracts\View\Factory; 

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot(Factory $view)
    {
        $view->composer('*', ViewComposer::class);
    }

    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton(ViewComposer::class);
    }
}

That's it, have fun building your next project!

Comments

Carlos Dominguez
public function register() { $this->app->singleton(ViewComposer::class); } what is the value of ViewComposer::class ? It doesnt recognize that class
Саша Благојевић
Hey Carlos, thanks for the comment. ViewComposer::class, or whatever name you give to it, it can be AnyNameComposer::class, is a class you create that holds your logic for extracting shared data and registers it with a method called compose.
Саша Благојевић
And thanks for pointing out, I missed to add that code snippet in the article. Such a noob move :D