timdev / typed-config
PHP应用程序的强类型配置
Requires
- php: ~7.4.0 || ~8.0.0 || ~8.1.0
- symfony/polyfill-php80: ^1.23
- symfony/polyfill-php81: ^1.23
Requires (Dev)
- timdev/devtools: ^0.1.6
README
这是什么?
一个小型库,提供对数组数据的严格类型访问,适用于嵌套数组的应用程序配置数据。嵌套值通过点字符串进行解引用。
用法
安装
使用composer安装此包
composer require timdev/typed-config
用法
简而言之
declare(strict_types=1); // This should already be set in your php.ini, but this library depends on it, // so you should verify that's set. ini_set('assert.exception', 1); // Could come from anywhere. $configArray = [ 'myapp' => [ 'some-api' => [ 'baseUrl' => 'https://example.com/v1/', 'timeout' => 30 ], 'allowed_ips' => [ '192.168.0.1', '192.168.0.50' ], 'optional_value' => null ] ]; $config = new Config($configArray); // Methods have narrow return type declarations: $baseUrl = $config->string('myapp.some-api.baseUrl'); $timeout = $config->int('myapp.some-api.timeout'); $allowed = $config->list('myapp.allowed_ips'); // Attempting to access an undefined value throws. $port = $config->int('invalid.key'); // Throws \TimDev\TypedConfig\Exception\KeyNotFound // Note that the main methods do not have nulalble return types. $optional = $config->bool('myapp.optional_value'); // Also throws! // Use ->nullable to access valeus that are defined, but might be null: $optional = $config->nullable->bool('myapp.optional_value');
假设和设计
为了有效地使用这个库,了解其设计和背后的假设非常重要。
假设:所有有效配置值都已定义
如上例所示,尝试访问未定义值的客户端代码将抛出异常。我们的观点是,库或应用程序应该提供完整的默认配置。这对用户总是有益的。这种设计意味着当用户尝试访问由于拼写错误或转录错误而无效的键时,他们会尽早收到警告。
如果您认为需要可选配置参数,则应提供默认值,如null或可能[]。
设计:依赖PHP的assert()
assert 是一个具有非常有用机制的语言构造:在生产环境中,它们被优化掉。这个库使用 assert() 在各种访问器方法返回配置值之前对它们进行类型检查。
如果您不熟悉影响 assert 工作的配置值,请在使用此库之前查看文档和您环境的配置。简而言之,您需要确保在开发和测试环境中assert.exception = 1和zend.assertion = 1。
因为这个库依赖于assert(),所以类型检查在生产环境中(其中zend.assertion = 0)被优化掉。这减少了开销,但意味着在开发环境中会抛出AssertionError的配置访问将在生产环境中
- 抛出
TypeError,或者 - 在哈希/列表不匹配的情况下不抛出任何内容。
动机
我们在使用mezzio构建应用程序时开发了此库,其中配置数据通常从数组中提取。数组很方便,但通常需要您
- 每次从您的
$config数组中提取某些值时都要进行防御性编码。 - 添加断言或注释,以便您的静态分析器能够弄清楚发生了什么。
这个库是尝试改善这种情况的一种尝试。
替代方案
还有其他从不同角度处理此问题的库。
selective-php/config 采用类似的方法,因为它提供了严格类型的检索(可能为null)的方法。与这个库不同,它在返回值时将值进行类型转换。我们采取更严格的态度,并认为类型不匹配是软件中的错误。其可空类型方法在配置键未定义时返回null,而我们认为这也是一个错误。
setbased/typed-config 同样类似。和之前讨论的库一样,它将尝试将配置数据中找到的内容转换为所需的类型,并且对未定义的配置键的宽容度比这个库更高。
league/config 通过帮助您为配置数据定义严格的模式采取了更为严格的方法。我们真的喜欢这种方法(至少在某些情况下),但有些困惑的是,它只提供了一个单例的 get(string $key): mixed 访问器。
待办事项
- 进行一些基准测试,以确定我们使用 assert 是否实际上提供了任何实质性的好处。