PHP持久化存储管理Laravel config配置
这个扩展为Laravel引入了持久配置存储库。
它的使用特别支持应用程序运行时配置,从数据库加载配置。
For license information check the LICENSE-file.
安装
The preferred way to install this extension is through composer.
任一次运行
php composer.phar require --prefer-dist illuminatech/config
或加入
"illuminatech/config": "*"
到你的composer.json的require部分。
用法
这个扩展允许使用外部存储(如关系数据库)中的数据重新配置已经创建的配置存储库。
它提供了特殊的配置存储库类Illuminatech config PersistentRepository
,它包装了任何给定的配置存储库,
添加一个层来保存和恢复来自持久存储的数据。
<?php
use IlluminateConfigRepository;
use IlluminatechConfigStorageDb;
use IlluminateSupportFacadesApp;
use IlluminatechConfigPersistentRepository;
$sourceConfigRepository = new Repository([
'foo' => [
'name' => 'Foo',
],
'bar' => [
'enabled' => false,
],
'other' => [
'value' => 'Some',
],
]);
$storage = new StorageDb(App::make('db.connection'));
$persistentConfigRepository = (new PersistentRepository($sourceConfigRepository, $storage))
->setItems([
'foo.name',
'bar.enabled',
]);
echo $persistentConfigRepository->get('foo.name'); // 如果存在则从数据库中返回值,否则从源存储库中返回值,在这个例子中- ` Foo `如果存在则从数据库中返回值,否则从源存储库中返回值,在这个例子中- ` Foo `
echo $persistentConfigRepository->get('other.value'); // 没有指定为“items”的键始终保持完整,在这种情况下-始终返回` Some `
没有指定为“items”的键始终保持完整,在这种情况下-始终返回“Some”配置数据,这些数据应该保存在通过IlluminatechConfigPersistentRepository::setItems()
定义的持久存储中。
只有显式定义为“项”的键才会被存储或从持久存储中检索。其他数据
源配置存储库中的内容将保持原样。
PersistentRepository完全装饰任何配置存储库,匹配IlluminateContracts config repository
,并可以替换Illuminate config repository
实例。
特别是,它允许你用Illuminatech config persistentpository
实例替换常规的Laravel配置,
将数据库配置应用到整个应用程序。你可以在AppServiceProvider
类中执行此操作。 例如:
<?php
namespace AppProviders;
use IlluminatechConfigStorageDb;
use IlluminateSupportServiceProvider;
use IlluminateContractsConfigRepository;
use IlluminatechConfigPersistentRepository;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
$this->app->extend('config', function (Repository $originConfig) {
$storage = new StorageDb($this->app->make('db.connection'));
$newConfig = (new PersistentRepository($originConfig, $storage))
->setItems([
'mail.contact.address' => [
'label' => __('Email address receiving contact messages'),
'rules' => ['sometimes', 'required', 'email'],
],
// ...
]);
return $newConfig;
});
// ...
}
}
注意:此扩展不提供应用程序配置替代的内置服务提供者,因为它可能不需要 对于特定的应用程序,而
IlluminatechConfig persistentpository
的使用不受此任务的限制。
您还可以为每个特定的应用程序实体管理持久配置。例如:假设我们需要允许
应用程序用户自定义其资料页面的外观,如更改颜色模式或启用/禁用侧边栏等。
这些设置可以通过绑定到用户Eloquent模型的IlluminatechConfigPersistentRepository
来管理。这样的模型类
可能看起来像下面这样:
<?php
namespace AppModels;
use IlluminateConfigRepository;
use IlluminatechConfigStorageDb;
use IlluminateDatabaseEloquentModel;
use IlluminatechConfigPersistentRepository;
class User extends Model
{
/**
* @var IlluminatechConfigPersistentRepository 特定于此模型的配置存储库。
*/
private $config;
/**
* 返回与此特定模型关联的配置。
*
* @return IlluminatechConfigPersistentRepository 配置存储库。
*/
public function getConfig(): PersistentRepository
{
if ($this->config === null) {
if (empty($this->id)) {
throw new InvalidArgumentException('Unable to get config for model without ID.');
}
$repository = new Repository($this->defaultConfigData());
$storage = (new StorageDb($this->getConnection()))
->setFilter(['user_id' => $this->id]); // 确保每个模型的配置不同
$this->config = (new PersistentRepository($repository, $storage))
->setItems($this->persistentConfigItems());
}
return $this->config;
}
/**
* 定义模型实例的默认配置。
*
* @return array config.
*/
private function defaultConfigData()
{
return [
'sidebar' => [
'enabled' => true,
],
'color' => [
'primary' => '#4099de',
'sidebar' => '#b3c1d1',
],
];
}
/**
* 定义配置项,这些配置项应该可以从web界面管理并存储在数据库中。
*
* @return array 配置项。
*/
private function persistentConfigItems(): array
{
return [
'sidebar.enabled' => [
'label' => 'Sidebar enabled',
'rules' => ['sometimes', 'required', 'boolean'],
],
'color.primary' => [
'label' => 'Primary color',
'rules' => ['sometimes', 'required', 'string'],
],
'color.sidebar' => [
'label' => 'Sidebar color',
'rules' => ['sometimes', 'required', 'string'],
],
];
}
}
它将允许您对每个用户记录分别操作持久配置,因此配置文件页面组合可以
如下图所示:
@php
/* @var $user AppModelsUser */
@endphp
@extends('layouts.main')
@section('content')
@if ($user->getConfig()->get('sidebar.enabled'))
@include('includes.sidebar', ['color' => $user->getConfig()->get('color.sidebar')])
@endif
<div style="background-color:{{ $user->getConfig()->get('color.primary') }};">
...
</div>
@endsection
配置项规范
应该保存在持久存储中的配置部分由' IlluminatechConfigPersistentRepository::setItems() '定义,
它接受一个“IlluminatechConfigItem”列表或它的配置数组。
每个配置项都应该定义一个键,该键指向源存储库中的目标值。
配置项也有几个属性,它支持创建web界面进行配置设置。
这些都是:
-
'id' - string,列表中项目的唯一id,该值将用于请求字段和表单输入。
-
'label' -字符串,配置值输入的详细标签。
-
'hint' -字符串,配置值或输入提示的详细描述。
-
'rules' -数组,值验证规则。
-
'cast' -字符串,要转换到的值的本机类型。
-
'encrypt' - bool,是否加密存储的值。
-
'options' -数组,项目的额外描述性选项,可以在你认为合适的时候使用。
由于只有'key'是必选项,项目可以通过定义该键的单个字符串指定。
以下是一些项目规格的例子:
<?php
use IlluminatechConfigItem;
use IlluminatechConfigPersistentRepository;
$persistentConfigRepository = (new PersistentRepository(...))
->setItems([
'some.config.value',
'another.config.value' => [
'label' => 'Custom label',
'rules' => ['required', 'numeric'],
],
[
'key' => 'array.config.value',
'rules' => ['required', 'array'],
'cast' => 'array',
],
new Item(['key' => 'explicit.object']),
]);
配置存储
声明的配置项可以保存到持久存储中,然后从中检索。
实际的项目存储可以是任何匹配IlluminatechConfigStorageContract
接口的类。
Following storages are available within this extension:
-
IlluminatechConfigStorageDb
—将配置存储在关系数据库中; -
IlluminatechConfigStorageEloquent
-使用Eloquent模型存储配置; -
IlluminatechConfigStoragePhp
-将配置存储在本地PHP文件中; -
IlluminatechConfigStorageArray
-将配置存储在运行时内存中;
有关更多细节,请参阅特定的存储类。
保存和恢复数据
IlluminatechConfig persistentpository
将自动从持久存储中检索配置项值
第一次尝试从中获取配置值。
<?php
use IlluminatechConfigPersistentRepository;
$persistentConfigRepository = (new PersistentRepository(...))
->setItems([
'some.config',
]);
$value = $persistentConfigRepository->get('some.config'); // 自动从持久存储加载数据。
你也可以使用restore()
方法手动从持久化存储中获取数据:
<?php
use IlluminatechConfigPersistentRepository;
$persistentConfigRepository = (new PersistentRepository(...))
->setItems([
'some.config',
]);
$persistentConfigRepository->restore(); // loads/re-loads data from persistent storage
小心! 在值恢复过程中出现的任何错误或异常都会被自动抑制。这是
在存储还没有准备好使用的情况下避免应用程序阻塞,例如:数据库表还不存在。
存储失败错误只会出现在应用程序日志中。您应该手动测试恢复的值
您的应用程序以避免意外行为。
要将配置数据保存到持久存储中,请使用save()
方法:
<?php
use IlluminatechConfigPersistentRepository;
$persistentConfigRepository = (new PersistentRepository(...))
->setItems([
'some.config',
'another.config',
]);
$persistentConfigRepository->save([
'some.config' => 'some persistent value',
'another.config' => 'another persistent value',
]);
通过常规配置库接口(例如通过方法set()
、push()
等)进行的更改不会自动执行
保存到持久存储中。但是,你可以使用synchronize()
方法将当前配置项的值保存到其中。
<?php
use IlluminatechConfigPersistentRepository;
$persistentConfigRepository = (new PersistentRepository(...))
->setItems([
'some.config',
'another.config',
]);
$persistentConfigRepository->set('some.config', 'new value'); // 在这一点上,持久存储没有更改
$persistentConfigRepository->synchronize(); // 将值保存到持久存储
提示:您可以在应用程序终止阶段调用
synchronize()
,以确保所做的所有更改 在应用程序运行期间保存。
方法reset()
清除保存到持久存储的所有数据,恢复原始(例如默认)配置存储库的值。
<?php
use IlluminateConfigRepository;
use IlluminatechConfigPersistentRepository;
$sourceConfigRepository = new Repository([
'some' => [
'config' => 'original value',
],
]);
$persistentConfigRepository = (new PersistentRepository($sourceConfigRepository, ...))
->setItems([
'some.config',
]);
$persistentConfigRepository->save([
'some.config' => 'new value',
]);
echo $persistentConfigRepository->get('some.config'); // outputs 'new value'
$persistentConfigRepository->reset(); // clears data in the persistent storage
echo $persistentConfigRepository->get('some.config'); // outputs 'original value'
你也可以使用resetValue()
方法来重置特定的配置键。
缓存
您可以使用PSR-16兼容缓存存储来提高配置项的性能
从持久存储中检索。例如:
<?php
use IlluminateConfigRepository;
use IlluminateSupportFacadesApp;
use IlluminatechConfigPersistentRepository;
$sourceConfigRepository = new Repository([
'some' => [
'config' => 'original value',
],
]);
$persistentConfigRepository = (new PersistentRepository($sourceConfigRepository, ...))
->setItems([
'some.config',
])
->setCache(App::make('cache.store'))
->setCacheKey('global-config')
->setCacheTtl(3600 * 24);
验证
每个配置项都有验证规则,默认匹配[
sometimes ,
required ]
。你可以很容易地
在保存配置之前,使用这些规则或使用Illuminatech config PersistentRepository::validate()
为用户输入创建一个验证。
例如:
<?php
/* @var $request IlluminateHttpRequest */
/* @var $config IlluminatechConfigPersistentRepository */
$validatedData = $config->validate($request->all()); // throws IlluminateValidationValidationException if validation fails.
// ...
你也可以使用IlluminatechConfig persistentpository::makeValidator()
方法来创建一个手动处理的验证器实例。
小心! 如果你没有使用IlluminatechConfigPersistentRepository::validate()
方法,请注意输入框中句点符号(.
)的用法。
默认情况下,Laravel将验证规则中的dots视为数组嵌套键分隔符。你要么换掉它们
通过->
字符串或手动定义IlluminatechConfigItem::$id
,以使其不包含句点。
创建配置web界面
这个扩展最常见的用例之一是创建一个web界面,允许控制应用程序
运行时配置。
IlluminatechConfig persistentpository
不仅用于应用配置-它还有助于创建一个
配置编辑界面。
用于配置管理的web控制器可能如下所示:
<?php
namespace AppHttpControllers;
use IlluminateHttpRequest;
use IlluminateContractsContainerContainer;
class ConfigController extends Controller
{
/**
* @var IlluminatechConfigPersistentRepository 持久化配置存储库,设置在`AppServiceProvider`。
*/
private $config;
public function __construct(Container $app)
{
$this->config = $app->get('config');
}
public function index()
{
$this->config->restore(); // 确保从数据库中恢复配置值
return view('config.form', ['items' => $this->config->getItems()]);
}
public function update(Request $request)
{
$validatedData = $this->config->validate($request->all());
$this->config->save($validatedData);
return back()->with('status', 'success');
}
public function restoreDefaults()
{
$this->config->reset();
return back()->with('status', 'success');
}
}
你可以在HTML表单输入组合中操作IlluminatechConfigItem
界面。例如:
...
<form ...>
...
@foreach ($items as $item)
<label>{{ $item->label }}</label>
<input type="text" name="{{ $item->id }}" value="{{ $item->getValue() }}">
<p>{{ $item->hint }}</p>
@endforeach
...
</form>
...
提示:你可以使用
IlluminatechConfigItem::$options
来设置动态表单输入的配置,指定 输入类型,CSS类等等。
小心! 请记住,PHP会自动替换非字母数字字符,如点(.
),破折号(-
)等
在原生POST
解析过程中,对config. conf
等键进行收集和验证。一些关键的是不可能的。
你需要为每个持久配置项手动设置IlluminatechConfigItem::$id
值,以防万一
<?php
use IlluminatechConfigPersistentRepository;
$persistentConfigRepository = (new PersistentRepository(...))
->setItems([
'some.config.value' => [
'id' => 'some_config_value',
],
'another-config-value' => [
'id' => 'another_config_value',
],
// ...
]);
提示:如果您使用JSON通过REST API接口提交配置项值,则不会面临此问题
格式化或通过原生(不是伪造的)“把”的要求。
型态转换
可以将数组等复杂类型的值作为持久化值进行操作。为此,你应该指定config item
通过IlluminatechConfigItem::$cast
进行类型转换。例如:
<?php
use IlluminateConfigRepository;
use IlluminatechConfigPersistentRepository;
$sourceConfigRepository = new Repository([
'some' => [
'array' => ['one', 'two', 'three'],
],
]);
$persistentConfigRepository = (new PersistentRepository($sourceConfigRepository, ...))
->setItems([
'some.array' => [
'cast' => 'array', // cast value from persistent storage to array
'rules' => ['sometimes', 'required', 'array'],
],
]);
$persistentConfigRepository->save([
'some.array' => ['five', 'six'],
]);
$persistentConfigRepository->restore();
var_dump($persistentConfigRepository->get('some.array') === ['five', 'six']); // outputs 'true'
加密
如果你打算操作敏感数据,如密码、API密钥等,你可能希望将它们存储为
加密字符串而不是普通字符串。这可以通过启用IlluminatechConfigItem::$encrypt
来实现。
例如:
<?php
use IlluminateConfigRepository;
use IlluminatechConfigPersistentRepository;
$sourceConfigRepository = new Repository([
'some' => [
'apiKey' => 'secret',
],
]);
$persistentConfigRepository = (new PersistentRepository($sourceConfigRepository, ...))
->setItems([
'some.apiKey' => [
'encrypt' => true, // encrypt value before placing it into the persistent storage
],
]);
注意,数据加密会影响配置存储库的性能。
垃圾回收
随着项目的发展,可能会出现新的配置项,也可能会出现冗余的配置项。
IlluminatechConfigPersistentRepository
自动忽略持久存储中的任何值,如果它没有
匹配由setItems()
设置的配置项。因此,存储的废弃值无论如何不会影响配置库
它们仍然可能消耗额外的存储空间。您可以手动从存储中删除所有废弃的值,
使用gc()
方法:
<?php
use IlluminateConfigRepository;
use IlluminatechConfigStorageDb;
use IlluminatechConfigPersistentRepository;
$sourceConfigRepository = new Repository([
'some' => [
'config' => 'original value',
],
]);
$storage = new StorageDb(...);
$storage->save([
'some.config' => 'some value',
'obsolete.config' => 'obsolete value',
]);
$persistentConfigRepository = (new PersistentRepository($sourceConfigRepository, $storage))
->setItems([
'some.config',
]);
$persistentConfigRepository->gc(); // 删除过时的。从存储配置
如果启用了IlluminatechConfig persistentpository::$gcEnabled
,垃圾回收将自动执行
每次配置值都通过save()
或synchronize()
方法保存。