time2split/time2configure

树形配置,带有文本插值

v1.0.0-alpha 2024-04-08 21:08 UTC

This package is auto-updated.

Last update: 2024-09-06 16:53:13 UTC


README

License: MIT Latest Stable Version Latest Unstable Version

Time2Configure 是一个 PHP 库,实现了带有值插值的树形配置的概念。

配置程序通常涉及从外部世界获取一些条目,例如通过输入一些命令行参数,然后在程序中使用这些条目。大多数情况下,程序会读取格式化的配置(如 jsonini 等),然后直接使用获取的结果作为程序配置。配置存储的实用格式可能包括 jsonphp 数组或其他树形格式。即使是平面的格式如 inicsv,也可以通过使用层次表示法(例如 parent.child)最终定义一个树形配置。树是表示配置的自然方式。

Time2Configure 提供了对树形配置的一般抽象,不仅关注任何格式,而且更关注存储和功能。此外,这些树形配置具有非常有用的能力,可以使用复杂的值插值语言。

安装

该库以 Composer 项目形式发布。

$ composer require time2split/time2configure

文档

一些示例

让我们通过一个示例来体验库的实际应用。

use Time2Split\Config\Configurations;

// Some configuration possibly loaded from an external file
$loadedConfig = [
    'text' => [
        'locale' => 'en_US',
        'encoding' => 'UTF-8'
    ],
    'database' => [
        'driver' => 'mysql',
        'port' => 3306,
        'database' => 'db',
        'username' => 'zuri',
        'password' => 'xxx',
    ],
];
$config = Configurations::ofTree($loadedConfig);

echo $config['text.locale'], "\n";
echo $config['database.driver'], "\n";
### Output ###
en_US
mysql

因为配置是树形的,我们可以将程序的一部分可见性降低到特定的子树。

$view = $config->subTreeView('database');
print_r($view->toArray());
### Output ###
Array
(
    [driver] => mysql
    [port] => 3306
    [database] => db
    [username] => zuri
    [password] => xxx
)

该库认为树中的每个节点都可以存储一个值,而不仅仅是叶子。

$config['database.driver'] = 'sqlite';
$config['database'] = 'an internal value';
print_r($config->toArray());
### Output ###
Array(
    [text.locale] => en_US
    [text.encoding] => UTF-8
    [database] => an internal value
    [database.driver] => sqlite
    [database.port] => 3306
    [database.database] => db
    [database.username] => zuri
    [database.password] => xxx
)

值插值

第二个主要特性是值插值。

值插值允许在访问条目时自动编译条目的值以生成动态的另一个值。以下是一个使用先前示例的 $config 的示例

// Get a new configuration instance with an interpolator
$iconfig = Configurations::treeCopyOf($config, Interpolators::recursive());

$iconfig['interpolated'] = '${text.locale} and ${text.encoding}';
echo $iconfig['interpolated'], "\n";

$iconfig['text.locale'] = 'UTF-16';
echo $iconfig['interpolated'], "\n";
### Output ###
en_US and UTF-8
UTF-16 and UTF-8

在这个示例中,我们使用了提供的插值器 Interpolators::recursive(),它会将文本值中遇到的每个 ${key} 标记替换为存储的 $config['key'] 值。(目前,这是库提供的唯一插值器。)

可以创建更复杂的插值语言。例如,pcp 项目在 parsica-php/parsica 项目的帮助下定义了一种更复杂的语言。该 pcp 插值语言 允许使用基于操作符的表达式(赋值、布尔值)甚至能够解析命令行参数。

插值原理很简单,但允许创建非常复杂的语言。

特性

配置层次结构

在许多场景中,存在一个默认的基础配置,用户可以修改它以创建最终的配置。Time2Configure 提供了一种创建配置列表的解决方案,其中只有最后一个可以实际修改。

$default = [
   'text' => [
       'locale' => 'en_US',
       'encoding' => 'UTF-8'
   ]
];
$default = Configurations::ofTree($default);
/*
   $default is the config to search for
   the unexistant entries of $config.
*/
$config = Configurations::emptyChild($default);

echo $config['text.locale'], "\n";

$config['text.locale'] = 'override';
echo $config['text.locale'], "\n";

$config['text.locale'] = null;
echo $config['text.locale'], "\n";

unset($config['text.locale']);
echo $config['text.locale'], "\n";
### Output ###
en_US
override

en_US

更普遍地说,这是一个非常有用的特性,允许进程免疫其配置被子进程修改,而无需复制。

装饰器

装饰器非常有用,可以给配置添加更多行为。例如,装饰器 Configurations::doOnRead() 能够在访问值时执行某个动作。

$tree = [
   'text' => [
       'locale' => 'en_US',
       'encoding' => 'UTF-8'
   ]
];
$config = Configurations::ofTree($tree);
$doEcho = Entries::consumeEntry(function ($key, $val) {
   echo "$key=$val\n";
});
$echoConfig = Configurations::doOnRead($config, $doEcho);

$echoConfig['text.locale'];
iterator_to_array($echoConfig);
### Output ###
text.locale=en_US
text.locale=en_US
text.encoding=UTF-8

还有一些映射装饰器可以使用原始条目值来创建新的值。以下是一个新示例

$config = Configurations::ofTree();
$config['url.php'] = 'https://php.ac.cn/support';

// Dereference an url and retrieves the header
$getHeader = Entries::mapValue(function ($value, $key) {

   if (\str_starts_with($key, 'url'))
       return \get_headers($value, true);

   return $value;
});
$deref = Configurations::mapOnRead($config, $getHeader);

print_r($deref['url.php']);
### Output ###
Array
(
   [0] => HTTP/1.1 200 OK
   [Server] => myracloud
   [Date] => Mon, 08 Apr 2024 20:00:43 GMT
   [Content-Type] => text/html; charset=utf-8
   [Transfer-Encoding] => chunked
   [Connection] => close
   [Content-language] => en
   [Permissions-Policy] => interest-cohort=()
   [X-Frame-Options] => SAMEORIGIN
   [Link] => <https://php.ac.cn/support>; rel=shorturl
   [Expires] => Mon, 08 Apr 2024 20:00:43 GMT
   [Cache-Control] => max-age=0
   [ETag] => "myra-3087d513"
)