所有控制器和视图的全局变量

Dee*_*yal 53 global-variables laravel laravel-4

在Laravel中我有一个表设置,我从BaseController中的表中获取了完整的数据,如下所示

public function __construct() 
{
    // Fetch the Site Settings object
    $site_settings = Setting::all();
    View::share('site_settings', $site_settings);
}
Run Code Online (Sandbox Code Playgroud)

现在我想访问$ site_settings.在所有其他控制器和视图中,所以我不需要一次又一次地编写相同的代码,所以任何人请告诉我解决方案或任何其他方式,以便我可以从表中获取一次数据并在所有控制器中使用它视图.

oll*_*ead 45

好吧,我将完全忽略其他答案充满的过度工程和假设的荒谬数量,并选择简单的选项.

如果您可以在每个请求期间进行单个数据库调用,那么该方法很简单,令人担忧的是:

class BaseController extends \Controller
{

    protected $site_settings;

    public function __construct() 
    {
        // Fetch the Site Settings object
        $this->site_settings = Setting::all();
        View::share('site_settings', $this->site_settings);
    }

}
Run Code Online (Sandbox Code Playgroud)

现在提供所有控制器扩展这个BaseController,他们可以做到$this->site_settings.

如果您希望限制多个请求之间的查询量,可以使用先前提供的缓存解决方案,但根据您的问题,简单答案是类属性.

  • 这是满足我需求的最佳解决方案.谢谢! (4认同)
  • 这不适用于从未命中控制器的视图(即在您的站点过滤器之一中显示的视图) (3认同)
  • 你的答案对于OPs问题是完全有效的,这就是为什么我没有对它进行downvote(虽然我觉得OP已经知道如何使用成员变量).但是,值得一提的是您的解决方案不起作用的常见情况. (3认同)
  • 是的,但是如果不是呢?许多站点(例如StackOverflow)至少会加载基本详细信息,例如错误页面的当前登录用户。您当然可以在每个处理程序中复制代码,但是最好找到通用的解决方案。 (2认同)

The*_*pha 44

首先,配置文件适用于此类事情,但您也可以使用另一种方法,如下所示(Laravel - 4):

// You can keep this in your filters.php file
App::before(function($request) {
    App::singleton('site_settings', function(){
        return Setting::all();
    });

    // If you use this line of code then it'll be available in any view
    // as $site_settings but you may also use app('site_settings') as well
    View::share('site_settings', app('site_settings'));
});
Run Code Online (Sandbox Code Playgroud)

要在任何控制器中获取相同的数据,您可以使用:

$site_settings = app('site_settings');
Run Code Online (Sandbox Code Playgroud)

有很多方法,只使用一个或另一个,你喜欢哪一个,但我正在使用Container.

  • @ollieread,这并不意味着这是一个错误的方法,我已经提到过`有很多方法,只需使用一个或另一个,你喜欢哪个,但我在我的答案中使用Container`.在你对任何答案投票之前先想想.我的回答也是正确的. (3认同)
  • 这个答案很好,在Laravel中有一百万种方法可以实现某些东西,你可以花很多时间在堆栈中重构,寻求完美,在这种情况下是Config类,但是以你自己的风格重新实现它是完全没问题的. (3认同)
  • +1这是一个很好的答案,根本不是过度设计,比将它放在你的控制器中更简单,更好 (2认同)
  • 我认为这是最好的答案.通过这种方法,变量在应用范围内确实是全局的. (2认同)

mal*_*hal 27

使用Config类:

Config::set('site_settings', $site_settings);

Config::get('site_settings');
Run Code Online (Sandbox Code Playgroud)

http://laravel.com/docs/4.2/configuration

在运行时设置的配置值仅为当前请求设置,不会转移到后续请求.

  • IMO这是更好的答案。 (2认同)

Kou*_*Das 9

在5+的Laravel中,您可以在config文件夹中创建一个文件并在其中创建变量并在整个应用程序中使用它.例如,我想根据网站存储一些信息.我创建了一个名为的文件siteVars.php,看起来像这样

<?php
return [
    'supportEmail' => 'email@gmail.com',
    'adminEmail' => 'admin@sitename.com'
];
Run Code Online (Sandbox Code Playgroud)

现在在routes,controller,views你可以用它访问

Config::get('siteVars.supportEmail')
Run Code Online (Sandbox Code Playgroud)

在视图中,如果我这样

{{ Config::get('siteVars.supportEmail') }}
Run Code Online (Sandbox Code Playgroud)

它将给出email@gmail.com

希望这可以帮助.

  • 使用BaseController的答案很好,但是这个确实可以确保您的数据可以在Controller以外的任何地方使用,因此我会继续使用它。您还可以在“ site_settings”中设置默认值,因此,如果缺少某些值,则不会出现错误 (2认同)

Ged*_*nas 9

BaseController 中最受欢迎的答案在 Laravel 5.4 上对我不起作用,但它们在 5.3 上起作用。不知道为什么。

我找到了一种适用于 Laravel 5.4 的方法,甚至可以为跳过控制器的视图提供变量。而且,当然,您可以从数据库中获取变量。

加入你的 app/Providers/AppServiceProvider.php

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        // Using view composer to set following variables globally
        view()->composer('*',function($view) {
            $view->with('user', Auth::user());
            $view->with('social', Social::all()); 
            // if you need to access in controller and views:
            Config::set('something', $something); 
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

信用:http : //laraveldaily.com/global-variables-in-base-controller/


小智 8

View::share('site_settings', $site_settings);
Run Code Online (Sandbox Code Playgroud)

添加

app->Providers->AppServiceProvider 文件引导方法

它是全局变量。


spe*_*ley 7

在 Laravel 5+ 中,只需设置一次变量并“全局”访问它,我发现将其作为属性添加到请求中最简单:

$request->attributes->add(['myVar' => $myVar]);
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用以下任何控制器访问它:

$myVar = $request->get('myVar');
Run Code Online (Sandbox Code Playgroud)

并从您的任何刀片使用:

{{ Request::get('myVar') }}
Run Code Online (Sandbox Code Playgroud)


Seb*_*rre 5

如果您担心重复访问数据库,请确保您的方法中内置了某种缓存,以便每个页面请求只调用一次数据库。

类似于(简化示例):

class Settings {

    static protected $all;

    static public function cachedAll() {
        if (empty(self::$all)) {
           self::$all = self::all();
        }
        return self::$all;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后您将访问Settings::cachedAll()而不是all()每个页面请求只会进行一次数据库调用。后续调用将使用缓存在类变量中的已检索内容。

上面的例子非常简单,并且使用了内存缓存,所以它只对单个请求有效。如果您愿意,您可以使用 Laravel 的缓存(使用 Redis 或 Memcached)来跨多个请求保存您的设置。您可以在此处阅读有关非常简单的缓存选项的更多信息:

http://laravel.com/docs/cache

例如,您可以向Settings模型添加一个方法,如下所示:

static public function getSettings() {
    $settings = Cache::remember('settings', 60, function() {
        return Settings::all();
    });
    return $settings;
}
Run Code Online (Sandbox Code Playgroud)

这只会每 60 分钟进行一次数据库调用,否则无论何时调用Settings::getSettings().

  • 然后你还必须实现缓存破坏逻辑。这更多地属于缓存管理策略,但在 Laravel 的情况下,最简单的方法是向模型的“保存()”事件添加一个侦听器,以清除缓存中的“设置”键(以确保它重新生成下次访问)。 (2认同)
  • 对于一个简单的问题,这是一种可怕的过度设计的方法。 (2认同)

Mar*_*ens 5

在Laravel 5.1中,我需要一个填充了所有视图中可访问的模型数据的全局变量.

我对ollieread的回答采用了类似的方法,并且能够在任何视图中使用我的变量($ notifications).

我的控制器位置:/app/Http/Controllers/Controller.php

<?php

namespace App\Http\Controllers;

use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;

use App\Models\Main as MainModel;
use View;

abstract class Controller extends BaseController
{
    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;

    public function __construct() {
        $oMainM = new MainModel;
        $notifications = $oMainM->get_notifications();
        View::share('notifications', $notifications);
    }
}
Run Code Online (Sandbox Code Playgroud)

我的模特位置:/app/Models/Main.php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use DB;

class Main extends Model
{
    public function get_notifications() {...
Run Code Online (Sandbox Code Playgroud)


nbs*_*bsp 5

我知道,对于5.4+来说仍然需要这样做,但是我也遇到了同样的问题,但是没有一个答案很干净,因此我尝试使用实现ServiceProviders。这是我所做的:

  1. 创建提供者 SettingsServiceProvider
    php artisan make:provider SettingsServiceProvider
  1. 创建了我需要的模型(GlobalSettings
    php artisan make:model GlobalSettings
  1. 在中编辑了生成的register方法\App\Providers\SettingsServiceProvider。如您所见,我使用雄辩的模型通过检索我的设置Setting::all()
 

    public function register()
    {
        $this->app->singleton('App\GlobalSettings', function ($app) {
            return new GlobalSettings(Setting::all());
        });
    }

 
  1. 在以下位置定义了一些有用的参数和方法(包括带有所需Collection参数的构造函数)GlobalSettings
 

    class GlobalSettings extends Model
    {
        protected $settings;
        protected $keyValuePair;

        public function __construct(Collection $settings)
        {
            $this->settings = $settings;
            foreach ($settings as $setting){
                $this->keyValuePair[$setting->key] = $setting->value;
            }
        }

        public function has(string $key){ /* check key exists */ }
        public function contains(string $key){ /* check value exists */ }
        public function get(string $key){ /* get by key */ }
    }

 
  1. 最后,我在 config/app.php
 

    'providers' => [
        // [...]

        App\Providers\SettingsServiceProvider::class
    ]

 
  1. 清除配置缓存后,php artisan config:cache可以按以下方式使用单例。
 

    $foo = app(App\GlobalSettings::class);
    echo $foo->has("company") ? $foo->get("company") : "Stack Exchange Inc.";

 

您可以在Laravel文档>服务容器和Laravel文档>服务提供商中阅读有关服务容器和服务提供商的更多信息。

这是我的第一个答案,我没有太多的时间写下来,因此格式化的空间有点小,但是我希望您能得到一切。


我忘了包含的boot方法SettingsServiceProvider,以使设置变量全局在视图中可用,因此您可以执行以下操作:

 

    public function boot(GlobalSettings $settinsInstance)
    {
        View::share('globalsettings', $settinsInstance);
    }

 

在调用引导方法之前,所有提供程序都已注册,因此我们可以仅使用GlobalSettings实例作为参数,以便Laravel可以将其注入。

在刀片模板中:

 

    {{ $globalsettings->get("company") }}

 


小智 5

您还可以使用我正在使用的Laravel 助手。只需在App文件夹下创建Helpers文件夹,然后添加以下代码:

namespace App\Helpers;
Use SettingModel;
class SiteHelper
{
    public static function settings()
    {
        if(null !== session('settings')){
          $settings = session('settings');
        }else{
          $settings = SettingModel::all();
          session(['settings' => $settings]);
        }
        return $settings;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后将其添加到您的配置> app.php 的别名下

'aliases' => [
....
'Site' => App\Helpers\SiteHelper::class,
]
Run Code Online (Sandbox Code Playgroud)

1. 在控制器中使用

use Site;
class SettingsController extends Controller
{
    public function index()
    {
        $settings = Site::settings();
        return $settings;
    }
}
Run Code Online (Sandbox Code Playgroud)

2. 在视图中使用:

Site::settings()
Run Code Online (Sandbox Code Playgroud)


小智 5

我找到了一种在 Laravel 5.5 上工作的更好的方法,并使视图可以访问变量。您可以从数据库中检索数据,通过导入模型来执行逻辑,就像在控制器中一样。

“*”表示您正在引用所有视图,如果您研究得更多,您可以选择要影响的视图。

添加您的应用程序/Providers/AppServiceProvider.php

<?php

    namespace App\Providers;

    use Illuminate\Contracts\View\View;

    use Illuminate\Support\ServiceProvider;
    use App\Setting;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
    */
    public function boot()
    {
        // Fetch the Site Settings object
        view()->composer('*', function(View $view) {
            $site_settings = Setting::all();
            $view->with('site_settings', $site_settings);
        });
    }

    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {

    }
}
Run Code Online (Sandbox Code Playgroud)


Zah*_*dri 5

用于控制器中的全局变量;您可以在 AppServiceProvider 中设置如下:

public function boot()
{
    $company=DB::table('company')->where('id',1)->first();
    config(['yourconfig.company' => $company]);
}
Run Code Online (Sandbox Code Playgroud)

用法

config('yourconfig.company');
Run Code Online (Sandbox Code Playgroud)