如何在Laravel 5中将数据传递给所有视图?


125

我想在Laravel 5应用程序的所有视图中访问一些默认数据。

我尝试搜索它,但仅找到Laravel 4的结果。我在这里阅读了文档“使用所有视图共享数据” 但我不知道该怎么做。以下代码应放在哪里?

View::share('data', [1, 2, 3]);

谢谢你的帮助。


好,您需要启动代码来管理此要求吗?
Safoor Safdar

1
在服务提供商中使用View :: share进行数据库调用的结果时,在运行刷新数据库迁移或尝试在数据库连接不可达的情况下运行黄昏时,应用程序会出错(长话说,.env.dusk.local为仅在服务提供商运行后使用)。如下所述,基本控制器或中间件是最好的。
安迪·洛贝尔

在使用*View Composer 时也要特别小心,尤其是在使用db查询时,因为它针对每个包含的子视图,组件等运行,因此最终可能会运行数百个不必要的查询,最好的方法是使用基本视图,例如布局。应用程序,然后根据需要向下传递数据。
安迪·洛贝尔

Answers:


220

这个目标可以通过不同的方法来实现,

1.使用BaseController

我喜欢设置方式,我制作了一个BaseController扩展Laravel自己的类Controller,并在那里设置了各种全局性的东西。然后,所有其他控制器都从BaseControllerLaravel的控制器扩展而来。

class BaseController extends Controller
{
  public function __construct()
  {
    //its just a dummy data object.
    $user = User::all();

    // Sharing is caring
    View::share('user', $user);
  }
}

2.使用过滤器

如果您知道要为整个应用程序中的每个请求的视图设置某种事实,您还可以通过在请求之前运行的过滤器来进行设置-这就是我在Laravel中处理User对象的方式。

App::before(function($request)
{
  // Set up global user object for views
  View::share('user', User::all());
});

要么

您可以定义自己的过滤器

Route::filter('user-filter', function() {
    View::share('user', User::all());
});

并通过简单的过滤器调用进行调用。

根据版本5更新。*

3.使用中间件

View::share一起使用middleware

Route::group(['middleware' => 'SomeMiddleware'], function(){
  // routes
});



class SomeMiddleware {
  public function handle($request)
  {
    \View::share('user', auth()->user());
  }
}

4.使用View Composer

View Composer还可以帮助绑定特定数据以不同方式进行查看。您可以将变量直接绑定到特定视图或所有视图。例如,您可以根据需要创建自己的目录来存储视图编辑器文件。并且这些视图组成文件通过Service提供与视图的交互。

View Composer方法可以使用不同的方式,第一个示例可以类似:

您可以创建一个App\Http\ViewComposers目录。

服务提供者

namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ViewComposerServiceProvider extends ServiceProvider {
    public function boot() {
        view()->composer("ViewName","App\Http\ViewComposers\TestViewComposer");
    }
}

之后,将此提供程序添加到config / app.php的“ providers”部分下。

TestViewComposer

namespace App\Http\ViewComposers;

use Illuminate\Contracts\View\View;

class TestViewComposer {

    public function compose(View $view) {
        $view->with('ViewComposerTestVariable', "Calling with View Composer Provider");
    }
}

ViewName.blade.php

Here you are... {{$ViewComposerTestVariable}}

此方法仅对特定视图有用。但是,如果要触发ViewComposer到所有视图,我们必须将此单个更改应用于ServiceProvider。

namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ViewComposerServiceProvider extends ServiceProvider {
    public function boot() {
        view()->composer('*',"App\Http\ViewComposers\TestViewComposer");
    }
}

参考

Laravel文档

进一步澄清 拉拉卡斯特集》

如果我这边仍然不清楚,请告诉我。


您的示例中缺少register()方法-这不是可选的
乔纳森

@jonathan谢谢指出,但是示例仅包含那些需要照顾的部分。与视图共享数据的角度。
萨福尔·萨夫达尔

您将过滤器放在哪里?也许最正确的答案是使用中间件组laravel.com/docs/5.3/middleware#middleware-groups或全局中间件
Toskan

7
这不是一个好主意,View作曲家为每个单独的视图创建作曲家实例,这意味着如果您运行1000次循环,将创建1000个作曲家实例,并且处理了1000次触发事件,这不是您想要的。
Reza Shadman '16

4
@RezaShadman是正确的!我是很难学到的。在安装了laravel-debugbar工具进行调查之前,我的应用程序运行如此缓慢。然后,我意识到所有8个查询在单个页面加载中都要执行大约15次。这是因为将为包含的每个刀片文件调用视图编辑器。那就是如果您使用星号*。如果您不使用,*则应该没问题。
Syclone

66

您可以创建自己的服务提供商ViewServiceProvider名称是通用的),也可以使用现有的AppServiceProvider

在您选择的提供程序中,将您的代码放入引导方法中。

public function boot() {
    view()->share('data', [1, 2, 3]);
}

这将使$data变量在所有视图中均可访问。

如果您想使用Facade而不是Helper,请更改view()->为,View::但不要忘记将use View;其放在文件的顶部。


谢谢,工作很棒。引导功能是用于这种情况的还是您建议创建自己的服务提供商?
拉格纳森,2015年

2
如果您只有一两个东西可以共享,则AppServiceProvider可以放进去,但是如果您还有其他东西,则应该考虑创建一个新的提供程序。
Marwelln

它正在工作,但是我今天才看到它不工作!使用composer update也不起作用。实际上,它根本没有触发boot()。我需要分享两个变量。
2015年

11
请注意,如果您要获取数据库记录,则此操作将不起作用,因为在执行迁移之前将调用该记录。因此,您基本上是在尝试获取数据库记录之前就尝试获取它们。至少对我来说似乎是这样。
lorey,2015年

1
不幸的是,这似乎不适用于共享已登录用户Auth :: user(),Safoor的#1答案,下面是这个答案:)
Stan Smulders

11

我发现这是最简单的一种。创建一个新的提供程序,并使用'*'通配符将其附加到所有视图。也可以在5.3中使用:-)

<?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()
    {
        //
    }
}

2
将此提供程序添加到您的config / app“ App \ Providers \ ViewServiceProvider :: class”中的提供程序数组中
Nadeem0035 16/10/7

8

最好的方法是使用 View::share('var', $value);

使用撰写问题"*"

考虑以下方法:

<?php
// from AppServiceProvider::boot()
$viewFactory = $this->app->make(Factory::class);

$viewFacrory->compose('*', GlobalComposer::class);

从示例刀片视图:

  @for($i = 0; $i<1000; $i++)
    @include('some_partial_view_to_display_i', ['toDisplay' => $i])
  @endfor

怎么了?

  • GlobalComposer类实例化1000采用倍 App::make
  • 该事件composing:some_partial_view_to_display_i被处理 1000次。
  • 类中的compose函数GlobalComposer被调用1000次。

但是局部视图some_partial_view_to_display_i与由组成的变量无关,GlobalComposer但会大大增加渲染时间。

最好的方法?

View::share与分组中间件一起使用。

Route::group(['middleware' => 'WebMiddleware'], function(){
  // Web routes
});

Route::group(['prefix' => 'api'], function (){

});

class WebMiddleware {
  public function handle($request)
  {
    \View::share('user', auth()->user());
  }
}

更新资料

如果您使用的是通过中间件管道计算的内容,则可以简单地侦听适当的事件,或将视图共享中间件放在管道的最后底部。


4

在文档中:

通常,您会将对共享方法的调用放在服务提供商的引导方法中。您可以自由地将它们添加到AppServiceProvider或生成单独的服务提供商来容纳它们。

我同意Marwelln,只需将其放在AppServiceProvider启动功能中即可:

public function boot() {
    View::share('youVarName', [1, 2, 3]);
}

我建议为该变量使用一个特定的名称,以避免与其他无“全局”变量引起的混淆或错误。


3

该文档可以听到https://laravel.com/docs/5.4/views#view-composers,但我将其分解

  1. 应用程序的根目录中查找目录app \ Providers并创建文件ComposerServiceProvider.php,然后将下面的文本复制并粘贴到该文件中并保存。

    <?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()
        {
            //
        }
    }
  2. 从应用程序的根目录中,打开Config / app.php,然后在文件中查找Providers部分,然后将“ App \ Providers \ ComposerServiceProvider”复制并粘贴到阵列中。

通过这样做,我们创建了Composer服务提供商。当您使用诸如http:// yourdomain / something / profile之类的Profile视图运行应用程序时,将调用服务提供者ComposerServiceProvider,并且实例化App \ Http \ ViewComposers \ ProfileComposer类,由于内部代码如下,因此调用Composer方法引导方法或功能。

 // Using class based composers...
 View::composer(
   'profile', 'App\Http\ViewComposers\ProfileComposer'
 );
  1. 如果刷新应用程序,则会出现错误,因为类App \ Http \ ViewComposers \ ProfileComposer尚不存在。现在创建它。

转到目录路径app / Http

  • 创建名为ViewComposers的目录

  • 创建文件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());
        }
    }

现在转到您的视图或本例中的Profile.blade.php并添加

{{ $count }}

并在个人资料页面上显示用户数。

要显示所有页面上的计数变化

// Using class based composers...
View::composer(
    'profile', 'App\Http\ViewComposers\ProfileComposer'
);

// Using class based composers...
View::composer(
    '*', 'App\Http\ViewComposers\ProfileComposer'
);

<?php和命名空间App \ Http \ ViewComposers; 使用Illuminate \ Contracts \ View \ View; 从
ProfileComposer.php中



1

在您的config文件夹中,您可以创建一个php文件名,例如“ variable.php”,其内容如下:

<?php

  return [
    'versionNumber' => '122231',
  ];

现在在所有视图中,您可以像

config('variable.versionNumber')

在某些情况下,我会这样做,因为信息是真正的全局信息,您可以从任何地方访问它。因此,我将配置文件称为“ global.php”,并在其中放置了所有我想在代码的所有其他部分都可以访问的内容。唯一的限制是,这是针对静态数据的,并且会被缓存。如果您不断更改数据,则不应以这种方式使用它。
eResourcesInc

1

1)在(app \ Providers \ AppServiceProvider.php)中

// in boot function
       view()->composer('*', function ($view) {
            $data = User::messages();
            $view->with('var_messages',$data);
        });

2)在您的用户模型中

  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)在您看来

 {{ $var_messages }}

0

Laravel 5.6方法:https ://laravel.com/docs/5.6/views#passing-data-to-views

与所有视图共享模型集合的示例(AppServiceProvider.php):

use Illuminate\Support\Facades\View;
use App\Product;

public function boot()
{
    $products = Product::all();
    View::share('products', $products);

}

2
如果您尝试使用空数据库创建一个新的应用程序,这将导致问题。
克里斯·赫伯特

0

您有两种选择:

1.通过启动功能共享在App \ Providers \ AppServiceProvider中

public function boot() { view()->share('key', 'value'); }

并在任何视图文件中访问$ key变量。

注意:请记住,您不能在此处访问当前的会话,身份验证,路由数据。仅当您要共享静态数据时,此选项才有用。假设您要基于当前用户,路由或任何自定义会话变量共享某些数据,那么您将无法使用这些数据。

  1. 使用帮助程序类在应用程序中的任何位置创建一个帮助程序类,并将其注册到config文件夹中app.php文件中的Alias数组中。

'aliases' => [ ..., 'Helper' => App\HelperClass\Helper::class, ],

并在App文件夹的HelperClass文件夹中创建Helper.php

namespace App\HelperClass;

class Helper
{
    public static function Sample()
    {
        //Your Code Here
    }
}

并在任何地方访问它 Helper::Sample()

在这里,您不会被限制使用Auth,Route,Session或任何其他类。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.