Laravel 5- 在所有模板中可用的全局Blade视图变量

71

在Laravel 5中,我该如何创建全局变量,以便在所有Blade模板中都可用?


8
http://laravel.com/docs/5.0/views#view-composers - lukasgeiter
9个回答

104

选项1:

您可以像这样使用view::share()

<?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');
    }

}

选项2: 使用一个composer:
1. 在`app\Composers\HomeComposer.php`创建一个composer文件。
注意:如果`app\Composers`不存在,则创建它。
<?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');
    }
}

然后,你可以通过以下方式将composer附加到任何视图
<?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');
    }

}

选项3: 将Composer添加到服务提供者,在Laravel 5中,我更喜欢将我的Composer放在App\Providers\ViewServiceProvider中。
1. 在app\Composers目录下创建一个Composer文件,命名为HomeComposer.php。 2. 将HomeComposer添加到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);
    }
}

1
您的回复对我帮助很大,不过如果您正在尝试访问 $user = Auth::user(); 并将 $user 变量传递到所有的 Blade 模板(包括页眉和内容部分),应该怎么办呢?我试过将 $user 变量放在 BaseController 中并共享它,但如果我 var_dump $user,数组中会得到一堆受保护的值。基本上,我想能够在整个应用程序的所有模板和视图中访问所有的认证用户变量。看起来很简单,但我已经花了几个小时去尝试弄明白它了。 - Chad Priddle
1
实际上这个可以工作: <?= $user['name']; ?> 但是这个却不行: {{ $user->name }} - Chad Priddle
@Chad Priddle 这个适用于数组 {{ $user['name'] }},而这个适用于对象 {{ $user->name }} - Emeka Mbah
我选择选项1时出现了“未找到类'App\Http\Controllers\View'”的错误。 - Kokodoko
推荐的方式应该是:使用View::share的服务提供者。 请注意,每次加载模板时都会调用composer“*”选项:如果您进行DB调用,则将为每个视图和子视图执行此操作! - Neekobus

40

按照此处建议创建一个新的服务提供者

将您的新服务提供者添加到配置文件中 (config/app.php)。

在您的新服务提供者的启动方法中使用:

View::share( 'something_cool', 'this is a cool shared variable' );
现在你可以在所有视图中使用$something_cool了。 希望这有所帮助。

1
此外,它是多次使用的变量在artisan down后的503页面上的终极解决方案。使用其他解决方案注入应用程序版本字符串作为缓存破坏参数或在更新时将其显示在页脚中是一项繁琐的任务。 (使用环境变量可能是最干净的解决方案) - luchaos
2
这是一个比批准答案更好的解决方案。 - Christophvh
我认为主要的区别在于用户询问如何在所有模板中使用全局变量。使用已接受的解决方案,用户需要记得扩展BaseController并调用parent::construct,而使用ViewComposer解决方案,他需要在每个控制器构造方法中调用View::composers以使变量可用。 - Nicolas
1
这应该被选为答案! - lewis4u
1
这是我最好的答案,易于使用。 - Ariful Islam

18

在寻找解决同一问题的方案时,在 Laravel 文档中找到了最佳解决方案。只需像这样在 AppServiceProvider 中使用 View::share

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

更多细节在此


2
Auth::user() 中没有起作用——在那个状态下它是空的——但位置是正确的,我只需要通过 composer 添加它 View::composer('*', function($view) { $view->with('current_user', Auth::user()); } 而不是使用 share。 - jave.web

11
你可以使用view composers来实现。视图组合器在模板加载时执行。您可以传递一个闭包,为该视图提供附加功能。使用视图组合器可以使用通配符。要为每个视图创建视图组合器,请使用*
View::composer('*', function($view)
{
    $view->with('variable','Test value');
});

您可以在文档中看到,也可以不使用闭包来完成此操作。
View::composer('*', 'App\Http\ViewComposers\ProfileComposer');

配置文件构建器类必须有一个compose方法。

视图构造器在渲染视图时执行。Laravel还有视图创建器,这些在实例化视图时执行。

您还可以选择使用带有setupLayout方法的BaseController。然后,您将加载的每个视图都通过setupLayout方法加载,该方法添加了一些附加数据。但是,使用视图构造器可以确保代码被执行。但是通过BaseController方法,您具有更多的灵活性,因为您可以跳过加载额外数据的步骤。

编辑:如Nic Gutierrez所述,您还可以使用视图共享。


这里与 view()->share 的区别在于,这只有在使用视图时才运行 - 但是使用 view()->share 时无论如何都会运行 - 比如你可能会在 API 调用中返回一些 JSON - 这不使用视图。 - Petecoop

4
此外,您还可以在Route.php文件中执行此操作:
view()->share('variableName', $variable);

2

我更愿意使用与view()门面助手配合使用的中间件。(Laravel 5.x)

中间件更易于维护,不会在控制器类树中造成混乱。

步骤

创建中间件

/app/Http/Middleware/TimezoneReset.php

为了创建一个中间件,你可以运行命令 php artisan make:middleware GlobalTimeConfig 使用share()方法来共享你需要共享的数据。
 <?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);
        }
    }

注册新创建的中间件

按照以下示例将中间件添加到您的中间件路由组中

/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',
        ],
    ];

从模板中访问数据

通过在View::share()方法调用中给定的键访问任何模板中的数据。

eg.:

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

编辑:Nic Gutierrez的服务提供商回答可能是更好(或最好)的解决方案。


1

你不仅可以使用 View::share('key', 'value'); 的方式,还可以像这样使用数组 View::share(['key'=>'value','key'=>'value'])


-2

您可以在Controller.php文件中添加:

use App\Category;

然后:

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

-7

你可以将它闪存到会话中,也可以在.env文件(静态变量)中定义它


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接