将配置存储在Laravel中的数据库中



我目前正在使用Laravel 5.2。我希望能够将配置属性(键值对(存储在数据库中,我愿意在运行时从应用程序和控制台(php artisan命令或Tinker(访问这些属性。

我的最佳选择是什么?

  • .env是一种方法,但它不是存储在数据库中,而是存储在文件中
  • Config::get是另一种方式,但它也写入文件。它可以配置为写入数据库吗
  • Cache::get被设置为与数据库一起工作,但它是临时的,而不是永久的,所以它是不可能的

我之所以对数据库配置感兴趣,是因为我们经常在部署过程中替换/删除文件。此外,存储加密的值也很好。这里的另一个重要功能是能够通过php artisantinker轻松获取值

  1. 进行迁移:php artisan make:migration CreateSettingsTable
<?php
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
class CreateSettingsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('settings', function (Blueprint $table) {
$table->id();
$table->string('key');
$table->string('value');
$table->timestamps();
$table->unique([
'key', //I add a unique to prevent double keys
]);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('settings');
}
}
  1. 制作模型:php artisan make:model Setting
<?php
namespace App;
use IlluminateDatabaseEloquentModel;
class Setting extends Model
{
protected $fillable = [
'key',
'value'
];
//I would normally do this in a repository,
// but for simplicity sake, i've put it in here :)
static public $settings = null;
static function get($key, $default = null)
{
if (empty(self::$settings)) {
self::$settings = self::all();
}
$model = self
::$settings
->where('key', $key)
->first();
if (empty($model)) {
if (empty($default)) {
//Throw an exception, you cannot resume without the setting.
throw new Exception('Cannot find setting: '.$key);
}
else {
return $default;
}
}
else {
return $model->value;
}
}
static function set(string $key, $value)
{
if (empty(self::$settings)) {
self::$settings = self::all();
}
if (is_string($value) || is_int($value)) {
$model = self
::$settings
->where('key', $key)
->first();
if (empty($model)) {
$model = self::create([
'key' => $key,
'value' => $value
]);
self::$settings->push($model);
}
else {
$model->update(compact('value'));
}
return true;
}
else {
return false;
}
}
}

请注意,我将get和set函数以及一个静态$settings变量直接添加到模型中,以使示例保持较小。通常我会选择制作一个存储库或服务(而不是服务提供商(来处理这些功能。这样,对于所有设置,您只查询数据库一次(每次请求(。你可以把这个放在缓存里,但这不是现在这个答案的一部分。

  1. 运行php artisan migrate在数据库中对表进行分页。

  2. 运行composer dump-autoload以确保修补程序能够找到Setting类。

  3. 使用类似php artisan tinker的内容(https://laravel.com/docs/7.x/artisan#tinker)要测试它,在这种情况下你可以做:

Setting::set('someKey', 'someValue'); //Set someKey to someValue
Setting::get('someKey'); //Get someKey, throws exception if not found
Setting::get('somekey2', 'someDefault'); //Shows someDefault because somekey2 is not set yet.

我希望它能有所帮助!:(

我使用的是laravel 9,使用的是spatie:spatie/laraavel设置中的包。

如果你遵循文档,你可以设置设置类,例如我想将支付网关设置存储到数据库中,即马来西亚的Securepay。

在设置文件夹中,App\settings将有一个新文件PaymentGatewaySettings.pp:

<?php
namespace AppSettings;
use SpatieLaravelSettingsSettings;
class PaymentGatewaySettings extends Settings
{
public string $env;
public string $uid;
public string $auth_token;
public string $checksum_token;
public static function group() : string
{
return 'payment_gateway';
}
}

在AppSeviceProvider.php中,我们在引导方法下添加了新行:

/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
/**
* Payment Gateway settings
*
*/
if(DB::table('settings')->where('group', 'payment_gateway')->exists()) {
config()->set('services', array_merge(config('services'), [
'securepay' => [
'env' => app(SecurepaySettings::class)->env,
'uid' => app(SecurepaySettings::class)->uid,
'auth_token' => app(SecurepaySettings::class)->auth_token,
'checksum_token' => app(SecurepaySettings::class)->checksum_token,
]
]));
}
}

如果我们不放入if语句,那么在想要运行php-artisan命令时,这将是一个错误。

在其他情况下,您可以扩展Illuminate\Foundation\Application类,并且可以使用类似于以下应用程序((的东西->getSecurePayEnv((,但为了设置配置,我仍然使用AppSeviceProvider.php中的引导方法。

希望能有所帮助。

我扩展了Rob Biermann方法来处理json数据

<?php
namespace AppModels;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;
use IlluminateSupportArr;
class Setting extends Model
{
use HasFactory;
protected $casts = [
'value' => 'array'
];
protected $fillable = [
'key',
'value'
];
/**
* @var Setting[]|IlluminateDatabaseEloquentCollection|null
*/
static public $settings = null;
static function getAll(string $key, $default = null){
if (empty(self::$settings)) {
self::$settings = self::all();
}
$keys = explode('.', $key);
$databaseKey = $keys[0];
unset($keys[0]);
$model = self
::$settings
->where('key', $databaseKey)
->first();
if (empty($model)) {
if (empty($default)) {
//Throw an exception, you cannot resume without the setting.
throw new Exception('Cannot find setting: ' . $key);
} else {
return $default;
}
} else {
return $model->value;
}
}
static function get(string $key, $default = null)
{
if (empty(self::$settings)) {
self::$settings = self::all();
}
$keys = explode('.', $key);
$databaseKey = $keys[0];
unset($keys[0]);
$model = self
::$settings
->where('key', $databaseKey)
->first();
if (empty($model)) {
if (empty($default)) {
//Throw an exception, you cannot resume without the setting.
throw new Exception('Cannot find setting: ' . $key);
} else {
return $default;
}
} else {
if(!empty( $keys)){
return Arr::get($model->value, implode('.',$keys));
}
if(is_string( $model->value)){
return $model->value;
}
if(Arr::has($model->value, 'default')){
return $model->value['default'];
}
return $model->value;
}
}
static function set(string $key, $value)
{
if (empty(self::$settings)) {
self::$settings = self::all();
}
$keys = explode('.', $key);
$databaseKey = $keys[0];
unset($keys[0]);
$model = self
::$settings
->where('key', $databaseKey)
->first();
if (empty($model)) {
if(!empty($keys)){
$array = [];
$model = self::create([
'key' => $key,
'value' => Arr::set($array, implode('.',$keys), $value)
]);
}
else{
$model = self::create([
'key' => $key,
'value' => $value
]);
}
self::$settings->push($model);
} else {
if(!empty($keys)){
$old = $model->value;
if(is_string($old)){
$old = ["default" => $old] ;
}
if(Arr::has($old, implode('.',$keys))){
$old = Arr::set($old, implode('.',$keys), $value);
}
else{
$old = Arr::add($old, implode('.',$keys), $value);
}
$model->update(['value' => $old]);
}
else{
if(is_array($model->value)){
$new = $model->value;
$new['default'] = $value;
$value = $new;
}
$model->update(['value' => $value]);
}
}
return true;
}

}

现在你可以使用了

Setting::get('someKey.key');
Setting::get('someKey.key.key1');
Setting::set('someKey.key', 'test');
Setting::set('someKey.key.key1', 'test');