我经常发现自己需要某种配置模块——用于存储应用程序参数、引导程序、模板变量等等。我通常会:
- 创建一个PHP文件来创建并返回一个数组,并通过include将其引入,或者
- 创建一个INI文件并通过parse_ini_file将其引入,或者
- 创建一个XML文件并通过SimpleXML将其吸入。
第一种方法提供了结构和类型的极大灵活性,但不能移植到其他语言(好吧,不容易;您可以将其转换为JSON,或将其序列化,等等)。第二种方法(INI文件)很方便,因为语法非常简洁,如果需要可以很容易地翻译成其他语言的其他项目;但是,您只能轻松深入两层(使用文件中的[sections])。第三种方法非常可移植,并允许嵌套结构—但不允许使用许多特定的PHP类型。
然而,我发现每个人都有自己的位置。然而,问题是:一旦我将它们引入到我的项目中,我该如何访问它们?更好的是,是否有一种方法可以引入多种类型的配置并仍然以相同的方式访问它们?
对现有的解决方案不满意,我做了唯一合乎逻辑的事情:我重新发明了轮子,并添加了一些我自己的新胎面。
解决方案最初是Phly_Config,它将成为一个通用存储容器,带有多个用于加载配置的适配器。然而,在与保罗交谈时,他注意到出现了两种工具。引用他的话:
- 通用数组/对象/结构实现。
- 配置适配器以将数据推送到结构中。
我开始考虑,并认为他是对的——于是Phly_Struct诞生了。
现在我已经大肆宣传了,这些工具究竟提供了什么?我认为例子是最好的总结。首先,Phly_Struct:
$array = array(
'key1 => 'value1',
'key2 => array(
'subkey1' => array(
'subsubkey1' => 'subsubvalue1',
'subsubkey2' => 'subsubvalue2'
),
'subkey2' => 'subvalue2'
),
'key3' => 'value3'
);
$struct = new Phly_Struct($array);
echo 'The value of the second subkey is ' . $struct->key2->subkey2;
$struct->key3 = 'Some new value!';
$struct->key2->subkey1->subsubkey1 = 'I am a third level value';
// Let's loop over values...
foreach ($struct->key2 as $key => $value) {
if (is_scalar($value)) {
echo "Key $key: $value\n";
}
}
// Let's grab a sub array to pass elsewhere
$subarray = $struct->key2->subkey1->toArray();
如您所见,Phly_Struct提供面向对象的值访问。您可以像处理对象属性一样检索和设置它们。此外,由于它实现了SPLIterator,您可以像遍历数组一样遍历Phly_Struct。
现在让我们转向Phly_Config:
$array = array(
'key1 => 'value1',
'key2 => array(
'subkey1' => array(
'subsubkey1' => 'subsubvalue1',
'subsubkey2' => 'subsubvalue2'
),
'subkey2' => 'subvalue2'
),
'key3' => 'value3'
);
// Load an in-memory array into the config
Phly_Config::load($array);
// Grab configuration; Phly_Config is a singleton, so this can be done at any
// time, and any configurations loaded will be available
$config = Phly_Config::getInstance();
// Load an INI file into the config, under the namespace 'ini'
Phly_Config::load('/path/to/some/config.ini', 'ini');
// Load an XML file into the config, under the namespace 'xml'
Phly_Config::load('/path/to/some/config.xml', 'xml');
// Load a PHP file returning an array into the config, under the namespace 'php'
Phly_Config::load('/path/to/some/config.php', 'php');
// By default, values are retrieved from the 'default' namespace, which is used
// if no namespace was specified when loading a config:
echo 'I am the third value: ' . $config->key3;
// Now grab the db host from the 'ini' namespace
$host = $config->ini->db->host;
// Set the db host in the xml config namespace
$config->xml->db->host = $host;
// Let's get back the whole db array from the xml config namespace
$db_data = $config->xml->db->toArray();
由于Phly_Config只是将配置结构加载到Phly_Struct中,因此您可以免费获得该类的所有语法优点。此外,由于Phly_Config是一个单例类,您可以在代码的不同点加载配置,并可以在其他任何地方访问这些值。
现在,您可以使用Phly_Config设置值。但是,它们只会影响当前实例;此时没有任何内容被写回配置文件。通常,配置是单向街道;您想加载配置数据并从您的程序访问它,但不想更改它。将来我可能会添加用于编写配置的实现,或者至少吐出格式化输出。同时,您始终可以使用PHP或JSON序列化对象。
随时欢迎评论、错误修复和其他反馈!
