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

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

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

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

213202 次浏览

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

类似(简化的例子) :

class Settings {


static protected $all;


static public function cachedAll() {
if (empty(self::$all)) {
self::$all = self::all();
}
return self::$all;
}
}

然后您将访问 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;
}

这将只是每60分钟进行一次数据库调用,否则每次调用 Settings::getSettings()时都会返回缓存值。

有两种选择:

  1. 在 app/library/YourClassFile.php 中创建一个 php 类文件

    您在其中创建的任何函数都可以在所有视图和控制器中轻松访问。

    如果它是一个静态函数,你可以很容易地通过类名访问它。

    确保在编写器文件中的自动加载类图中包含“ app/library”。

  2. 在 app/config/app.php 中创建一个变量,您可以使用

    Get (‘ variable _ name’) ;

希望这个能帮上忙。

编辑1:

例如我的第一点:

// app/libraries/DefaultFunctions.php


class DefaultFunctions{


public static function getSomeValue(){
// Fetch the Site Settings object
$site_settings = Setting::all();
return $site_settings;
}
}


//composer.json


"autoload": {
"classmap": [
..
..
..
"app/libraries" // add the libraries to access globaly.
]
}


//YourController.php


$default_functions  = new DefaultFunctions();
$default_functions->getSomeValue();

首先,一个配置文件适合于这种情况,但是您也可以使用另一种方法,如下所示(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'));
});

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

$site_settings = app('site_settings');

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

好吧,我打算完全忽略其他答案充斥的过度设计和假设的荒谬数量,选择简单的选项。

如果在每个请求期间只有一个数据库调用,那么该方法就很简单,令人担忧:

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


}

现在假设您的所有控制器都扩展了 BaseController,那么它们只需执行 $this->site_settings即可。

如果希望限制跨多个请求的查询数量,可以像前面提供的那样使用缓存解决方案,但根据您的问题,简单的答案是类属性。

使用 Config 类:

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


Config::get('site_settings');

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

在运行时设置的配置值只针对当前请求设置,不会传递到后续请求。

在 Laravel 5.1中,我需要一个全局变量,其中包含可在所有视图中访问的模型数据。

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

我的控制器位置:/app/Http/Controller/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);
}
}

我的模型位置:/app/Model/Main.php

namespace App\Models;


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


class Main extends Model
{
public function get_notifications() {...
View::share('site_settings', $site_settings);

加到

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

是全局变量。

在 Laravel,5 + 可以在 config 文件夹中创建一个文件,并在该文件夹中创建变量,然后在整个应用程序中使用该文件。 例如,我想存储一些基于站点的信息。 我创建了一个名为 site_vars.php的文件, 就像这样

<?php
return [
'supportEmail' => 'email@gmail.com',
'adminEmail' => 'admin@sitename.com'
];

现在在 routescontrollerviews中你可以使用

Config::get('site_vars.supportEmail')

如果我这样做

\{\{ Config::get('site_vars.supportEmail') }}

它将发送 email@gmail.com

希望这个能帮上忙。

编辑 - 您还可以在 .env文件中定义 vars,并在这里使用它们。 在我看来,这是最好的方法,因为它使您可以灵活地在本地机器上使用所需的值。

所以,你可以在数组中做这件事

'supportEmail' => env('SUPPORT_EMAIL', 'defaultmail@gmail.com')

重要的-在您这样做之后,不要忘记在生产环境中这样做

php artisan config:cache

如果仍然有一些问题,那么你可以这样做(通常它永远不会发生,但仍然如果它曾经发生过)

php artisan cache:clear
php artisan config:cache

在你的 local env,总是这样做后,添加它

php artisan config:clear

最好不要在本地缓存配置变量。在缓存的情况下,这将删除缓存并加载新的更改。

BaseController 中最流行的答案在 Laravel5.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);
});
}
}

来源: http://laraveldaily.com/global-variables-in-base-controller/

在 Laravel 5 + 中,只需设置一个变量并访问它的“全局”,我发现最简单的方法就是将它作为一个属性添加到 Request:

$request->attributes->add(['myVar' => $myVar]);

然后你可以通过任何控制器访问它,使用:

$myVar = $request->get('myVar');

从你的任何刀片使用:

\{\{ Request::get('myVar') }}

我明白了,5.4 + 仍然需要这个,我也遇到了同样的问题,但是没有一个答案是足够简洁的,所以我尝试用 ServiceProviders实现这个可用性。我是这么做的:

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


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


 
  1. GlobalSettings中定义了一些有用的参数和方法(包括具有所需 Collection参数的构造函数)
 


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 Docs > Service Container and Laravel Docs > Service Provider 中了解更多关于服务容器和服务提供者的信息。

这是我的第一个答案,我没有太多的时间写下来,所以格式有点空白,但我希望你得到的一切。


我忘记了包含 SettingsServiceProviderboot方法,以使视图中的设置变量全局可用,所以这里是:

 


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


 

在调用引导方法之前,所有的提供程序都已注册,因此我们可以只使用 GlobalSettings实例作为参数,这样就可以由 Laravel 注入它。

刀片模板:

 


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


 

你也可以使用我正在使用的 Laravel 助手。 只需在 应用程序文件夹下创建 帮手文件夹 然后添加以下代码:

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;
}
}

然后将其添加到 config > app.php 的别名下

'aliases' => [
....
'Site' => App\Helpers\SiteHelper::class,
]

1. 在 控制员中使用

use Site;
class SettingsController extends Controller
{
public function index()
{
$settings = Site::settings();
return $settings;
}
}

2. 在 观景中使用:

Site::settings()

我已经找到了一个更好的方法,它可以在 Laravel 5.5上工作,并且可以通过视图访问变量。你可以从数据库中检索数据,通过导入模型来完成逻辑,就像在控制器中一样。

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

添加应用程序/提供程序/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()
{


}
}

使用 middlwares

1-创建任意名称的中间件

<?php


namespace App\Http\Middleware;


use Closure;
use Illuminate\Support\Facades\View;


class GlobalData
{
public function handle($request, Closure $next)
{
// edit this section and share what do you want
$site_settings = Setting::all();
View::share('site_settings', $site_settings);
return $next($request);
}
}

2-在 Kernal.php中注册中间件

protected $routeMiddleware = [
.
...
'globaldata' => GlobalData::class,
]

现在组你的路线与 globaldata中间件

Route::group(['middleware' => ['globaldata']], function () {
//  add routes that need to site_settings
}

在文件供应商 autoload.php 中,按如下方式定义目标变量,应该位于最上一行。

$global_variable = "Some value";//the global variable

在任何地方访问该全局变量:-

$GLOBALS['global_variable'];

享受:)

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

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

用途

config('yourconfig.company');

我知道我来晚了,但这是我找到的最简单的方法。 在 app/Providers/AppServiceProvider.php中,在启动方法中添加变量。这里我从 DB 中检索所有国家:

public function boot()
{
// Global variables
view()->composer('*',function($view) {
$view->with('countries', Country::all());
});
}