I want to have some default data accessible in all views in my Laravel 5 application.
I have tried to search for it but only find results for Laravel 4. I have read the documentation 'Sharing Data With All Views' here but I can't understand what to do. Where should the following code be placed?
View::share('data', [1, 2, 3]);
Thanks for your help.
1) In (app\Providers\AppServiceProvider.php)
// in boot function
view()->composer('*', function ($view) {
$data = User::messages();
$view->with('var_messages',$data);
});
2) in Your User Model
public static function messages(){ // this is just example
$my_id = auth()->user()->id;
$data= Message::whereTo($my_id)->whereIs_read('0')->get();
return $data; // return is required
}
3) in Your View
{{ $var_messages }}
You can either create your own service provider (ViewServiceProvider
name is common) or you can use the existing AppServiceProvider
.
In your selected provider, put your code in the boot method.
public function boot() {
view()->share('data', [1, 2, 3]);
}
This will make a $data
variable accessible in all your views.
If you rather want to use the facade instead of the helper, change view()->
to View::
but don't forget to have use View;
at the top of your file.
The documentation is hear https://laravel.com/docs/5.4/views#view-composers but i will break it down
Look for the directory app\Providers in the root directory of your application and create the file ComposerServiceProvider.php and copy and past the text below into it and save it.
<?php
namespace App\Providers;
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
class ComposerServiceProvider extends ServiceProvider
{
/**
* Register bindings in the container.
*
* @return void
*/
public function boot()
{
// Using class based composers...
View::composer(
'profile', 'App\Http\ViewComposers\ProfileComposer'
);
// Using Closure based composers...
View::composer('dashboard', function ($view) {
//
});
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
//
}
}
From the root of your application open Config/app.php and look for the Providers section in the file and copy and past this 'App\Providers\ComposerServiceProvider', to the array.
By doing this, we have created the Composer Service Provider. When you run your application with the view Profile like so http://yourdomain/something/profile, the service provider ComposerServiceProvider is called and the class App\Http\ViewComposers\ProfileComposer is instantiated calling the method Composer due to the code below inside the boot method or function.
// Using class based composers...
View::composer(
'profile', 'App\Http\ViewComposers\ProfileComposer'
);
Go to the directory path app/Http
Create the directory called ViewComposers
Create the file ProfileComposer.php.
class ProfileComposer
{
/**
* The user repository implementation.
*
* @var UserRepository
*/
protected $users;
/**
* Create a new profile composer.
*
* @param UserRepository $users
* @return void
*/
public function __construct(UserRepository $users)
{
// Dependencies automatically resolved by service container...
$this->users = $users;
}
/**
* Bind data to the view.
*
* @param View $view
* @return void
*/
public function compose(View $view)
{
$view->with('count', $this->users->count());
}
}
Now go to your view or in this case Profile.blade.php and add
{{ $count }}
and that will show the count of users on the profile page.
To show the count on all pages change
// Using class based composers...
View::composer(
'profile', 'App\Http\ViewComposers\ProfileComposer'
);
To
// Using class based composers...
View::composer(
'*', 'App\Http\ViewComposers\ProfileComposer'
);
I think that the best way is with View Composers
. If someone came here and want to find how can do it with View Composers way, read my answer => How to share a variable across all views?
Laravel 5.6 method: https://laravel.com/docs/5.6/views#passing-data-to-views
Example, with sharing a model collection to all views (AppServiceProvider.php):
use Illuminate\Support\Facades\View;
use App\Product;
public function boot()
{
$products = Product::all();
View::share('products', $products);
}
The documentation is here https://laravel.com/docs/5.4/views#view-composers but i will break it down 1.Look for the directory Providers in your root directory and create the for ComposerServiceProvider.php with content
Inside your config folder you can create a php file name it for example "variable.php" with content below:
<?php
return [
'versionNumber' => '122231',
];
Now inside all the views you can use it like
config('variable.versionNumber')
The best way would be sharing the variable using View::share('var', $value);
Problems with composing using "*"
:
Consider following approach:
<?php
// from AppServiceProvider::boot()
$viewFactory = $this->app->make(Factory::class);
$viewFacrory->compose('*', GlobalComposer::class);
From an example blade view:
@for($i = 0; $i<1000; $i++)
@include('some_partial_view_to_display_i', ['toDisplay' => $i])
@endfor
What happens?
GlobalComposer
class is instantiated 1000 times using
App::make
. composing:some_partial_view_to_display_i
is handled
1000 times.compose
function inside the GlobalComposer
class is called 1000 times.But the partial view some_partial_view_to_display_i
has nothing to do with the variables composed by GlobalComposer
but heavily increases render time.
Best approach?
Using View::share
along a grouped middleware.
Route::group(['middleware' => 'WebMiddleware'], function(){
// Web routes
});
Route::group(['prefix' => 'api'], function (){
});
class WebMiddleware {
public function handle($request)
{
\View::share('user', auth()->user());
}
}
Update
If you are using something that is computed over the middleware pipeline you can simply listen to the proper event or put the view share middleware at the last bottom of the pipeline.
I found this to be the easiest one. Create a new provider and user the '*'
wildcard to attach it to all views. Works in 5.3 as well :-)
<?php
namespace App\Providers;
use Illuminate\Http\Request;
use Illuminate\Support\ServiceProvider;
class ViewServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
* @return void
*/
public function boot()
{
view()->composer('*', function ($view)
{
$user = request()->user();
$view->with('user', $user);
});
}
/**
* Register the application services.
*
* @return void
*/
public function register()
{
//
}
}
You have two options:
1. Share via ?Boot
function in App\Providers\AppServiceProvider
:
public function boot()
{
view()->share('key', 'value');
}
And access $key
variable in any view file.
Note
: Remember that you can't access current Session
, Auth
, Route
data here. This option is good only if you want to share static data. Suppose you want to share some data based on the current user , route, or any custom session variable you won't be able to do with this.
2. Use of a helper class:
Create a helper class anywhere in your application and register it in Alias array in app.php
file in config
folder.
'aliases' => [
...,
'Helper' => App\HelperClass\Helper::class,
],
and create Helper.php
in HelperClass folder within App folder:
namespace App\HelperClass;
class Helper
{
public static function Sample()
{
//Your Code Here
}
}
and access it anywhere like Helper::Sample()
.
You will not be restricted
here to use Auth
, Route
, Session
, or any other classes.
for example you can return list of all tables in database to the all views of Controller like this :
public function __construct()
{
$tables = DB::select('SHOW TABLES'); // returns an array of stdObjects
view()->share('tables', $tables);
}
In the documentation:
Typically, you would place calls to the share method within a service provider's boot method. You are free to add them to the AppServiceProvider or generate a separate service provider to house them.
I'm agree with Marwelln, just put it in AppServiceProvider
in the boot function:
public function boot() {
View::share('youVarName', [1, 2, 3]);
}
I recommend use an specific name for the variable, to avoid confussions or mistakes with other no 'global' variables.
Source: Stackoverflow.com