time2split / time2configure
树形配置,带有文本插值
Requires
- php: >=8.2
- time2split/time2help: >=1.0-alpha < 2.0
Requires (Dev)
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^11
This package is auto-updated.
Last update: 2024-09-06 16:53:13 UTC
README
Time2Configure 是一个 PHP 库,实现了带有值插值的树形配置的概念。
配置程序通常涉及从外部世界获取一些条目,例如通过输入一些命令行参数,然后在程序中使用这些条目。大多数情况下,程序会读取格式化的配置(如 json
、ini
等),然后直接使用获取的结果作为程序配置。配置存储的实用格式可能包括 json
、php
数组或其他树形格式。即使是平面的格式如 ini
或 csv
,也可以通过使用层次表示法(例如 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" )