我有一个应用程序,存储配置设置到数据库
数据库表由两个文本列key
和value
组成。
我想在应用程序开始时读取所有值一次,然后通过
使其可用于整个应用程序 MySettings::set(key, value)
和MySettings::get(key)
我相信最好的方法是通过$app->singleton
,但由于我是Laravel的新手,我真的无法理解这是如何完成的:
当然,如果有更好的方法(不需要单例),我很乐意知道如何做到这一点。
通常人们将他们的配置细节保存在.env
文件中。在laravel文档中阅读env。我在这里写了一篇关于env使用的长篇文章。在数据库中保存值是没有必要的,也可能不建议,直到你有一些其他的配置,你需要在数据库中保存conf值。
但是如果你想这样做,你可以从数据库中获取所有变量,并将其保存在PHP superglobal variables
中。点击这里阅读。
从这些变量中拿出你的图片,仔细阅读它们以及它们被使用的原因。然后选择一个最适合你的。$_ENV
似乎适合你的情况。
:
我想读取所有的值一次在我的应用程序的开始
我认为你还没有清楚地理解整个请求响应阶段。你的应用程序没有"启动"这样的事情。每次请求到达服务器时,你的应用程序启动,准备所有的变量并将它们加载到内存中。一旦发送响应,一切都将被销毁。因此,即使您保留一个单例类,它也会在每次请求时被一次又一次地创建。但是,session, cookie等是持久的,它们不会消失。
更新1:因此,使用超全局变量被认为是一种不好的做法。所以回到最初的问题——如何在Laravel中创建一个单例类。假设我们在L5上,我们可以简单地:- 自动装载composer.json
- 遵循命名空间
这两种技术在这里都有很好的解释。
更新2:如何在L5中创建作为Provider
的单例类
这是我最近才知道的一种非常简洁的技术,它完全符合提问者的需要。
基于Laravel架构,当服务器端收到请求时,Laravel启动并binds
一些服务,如Auth
, Cache
等。同样,你也可以绑定自己的Provider
,这样在启动时,你的类将自动实例化,你可以在整个应用程序中使用它们。
步骤1:使用php artisan命令创建ServiceProvider
:
php artisan make:provider DatabaseConfigurationServiceProvider
这将在你的Providers
文件夹中创建一个提供商。
步骤2:像这样填充你的新类:
<?php
namespace App'Providers;
use App'Services'DatabaseConfigurationService;
use Illuminate'Support'ServiceProvider;
class DatabaseConfigurationServiceProvider extends ServiceProvider
{
protected $defer = true;
public function boot()
{
}
public function register()
{
$this->app->singleton('dbconf', function() {
return new DatabaseConfigurationService();
});
}
public function provides()
{
return ['dbconf'];
}
}
我们在这里做的是:
- 扩展
ServiceProvider
。所有的供应商都必须这样做。 - 使
defer
为true,因为我们不想在每个请求上加载此配置。相反,我们希望在需要时加载这个类。如果你想在每个请求上加载你的配置,那么你把这个值设为true,然后也删除整个provides()
函数,因为我们不再需要它了。然后会发生的是,每次新的请求来了,这个类将被调用,它将加载所有的数据库配置值,并将存储它们,直到请求被处理。然后我们重写register()
方法,将这个提供程序注册到你想调用的类中。我们注册了一个名称dbconf
,它随后成为全局$app
变量的标识符,我们还绑定了一个类DatabaseConfigurationService()
。注意,这个类将在后面定义。还要注意,这个class is binded in a
单例fashion
意味着它将只实例化一次。 - 然后我们创建了一个
provides()
方法,只有当您将$defer
设置为true时才需要。这将返回在加载该类时应该加载的绑定名称。
步骤3:创建DatabaseConfigurationService
类
要执行此步骤,您需要在app文件夹中创建一个新文件夹Services
。然后编写以下代码:
<?php
namespace App'Services;
use Illuminate'Support'Facades'Log;
class DatabaseConfigurationService
{
public static $somevar;
public function __construct()
{
//Do some tasks such as getting username/password from your .env file
}
public static function getValues()
{
//Get all your values here.
}
}
我们所做的是:
- 创建这个类,它将在应用程序启动/需要时由
Provider
类调用(取决于$defer)。
步骤4:为您的新提供者创建一个Facade
:
<?php
namespace App'Facades;
use Illuminate'Support'Facades'Facade;
class DatabaseConfiguration extends Facade
{
protected static function getFacadeAccessor()
{
return 'dbconf';
}
}
步骤5:在config/app.php
在
provider
数组中添加以下行。应用' '供应商DatabaseConfigurationServiceProvider
在别名数组中添加下面一行。
'DatabaseConfiguration '=> 'App'Facades'DatabaseConfiguration'
第6步:最后,你现在可以使用你的Provider
在你的控制器,像这样:
注意:我知道这是一个有点冗长的过程,但这是推荐的方法。一旦你做了几个Providers
,你就会明白这是一个相当简单的过程。—使用"use DatabaseConfiguration;
"导入-使用DatabaseConfiguration::getValues()
你也可以实现你自己的Singleton,它可以让你更容易理解到底发生了什么:
<?php
namespace App'Helpers;
class Settings
{
private static $instance;
private static $settings = [];
private function __construct(){}
public static function getInstance(){
if(is_null(static::$instance))
static::$instance= new Settings;
return static::$settings;
}
public static function getKey($key)
{
if(array_key_exists($key , static::$settings))
return static::$settings[$key];
return null;
}
public static function setKey($key , $value)
{
static::$settings[$key] = $value;
}
}
<?php
namespace App'Http'Controllers;
//...
class HelloController extends Controller
{
public function index()
{
Settings::getInstance();
Settings::setKey("foo", "bar");
Settings::getKey("foo"); // returns bar
// as long as you don't change "foo" again, it will always be "bar" anywhere in your app
}
}
- 在app文件夹中创建一个名为Helpers的文件夹
- 在Helpers文件夹中创建Settings.php
- 在laravel目录(不是app目录)中运行"Composer dump- autolload "