tomphp / config-service-provider
Requires
- php: ^5.6|^7.0
- beberlei/assert: ^2.6
- tomphp/exception-constructor-tools: ^1.0.0
Requires (Dev)
- friendsofphp/php-cs-fixer: 2.0.0-alpha
- league/container: ^2.0.2
- phpunit/phpunit: ^5.5.4
- pimple/pimple: ^3.0.0
- squizlabs/php_codesniffer: *
- symfony/yaml: ^3.1.4
Suggests
- league/container: Small but powerful dependency injection container http://container.thephpleague.com
- pimple/pimple: A small PHP 5.3 dependency injection container http://pimple.sensiolabs.org
- symfony/yaml: For reading configuration from YAML files
README
此包允许您通过配置数组或文件配置您的应用程序和依赖注入容器(DIC)。目前支持的容器包括
安装
可以使用 composer 轻松安装。
$ composer require tomphp/container-configurator
示例用法
<?php use League\Container\Container; // or Pimple\Container use TomPHP\ContainerConfigurator\Configurator; $config = [ 'db' => [ 'name' => 'example_db', 'username' => 'dbuser', 'password' => 'dbpass', ], 'di' => [ 'services' => [ 'database_connection' => [ 'class' => DatabaseConnection::class, 'arguments' => [ 'config.db.name', 'config.db.username', 'config.db.password', ], ], ], ], ]; $container = new Container(); Configurator::apply()->configFromArray($config)->to($container); $db = $container->get('database_connection');
从磁盘读取文件
除了以数组形式提供配置,您还可以将文件模式匹配列表提供给 fromFiles
函数。
Configurator::apply() ->configFromFile('config_dir/config.global.php') ->configFromFiles('json_dir/*.json') ->configFromFiles('config_dir/*.local.php') ->to($container);
configFromFile(string $filename)
从单个文件中读取配置。
configFromFiles(string $pattern)
使用通配符模式从多个文件中读取配置。
合并
读取器按照指定的顺序匹配文件。当读取文件时,其配置会被合并;覆盖任何匹配的键。
支持的格式
目前默认支持 .php
和 .json
文件。PHP 配置文件 必须 返回一个 PHP 数组。
.yaml
和 .yml
文件可以在有 symfony/yaml
包时读取。运行
composer require symfony/yaml
来安装它。
应用程序配置
配置数组中的所有值都可以通过 DIC 访问,键由分隔符(默认为 .
)分隔,并以前缀字符串(默认为 config
)开头。
示例
$config = [ 'db' => [ 'name' => 'example_db', 'username' => 'dbuser', 'password' => 'dbpass', ], ]; $container = new Container(); Configurator::apply()->configFromArray($config)->to($container); var_dump($container->get('config.db.name')); /* * OUTPUT: * string(10) "example_db" */
访问整个子数组
对于您想要整个子数组而不是单个值的情况,也提供了完整的子数组。
示例
$config = [ 'db' => [ 'name' => 'example_db', 'username' => 'dbuser', 'password' => 'dbpass', ], ]; $container = new Container(); Configurator::apply()->configFromArray($config)->to($container); var_dump($container->get('config.db')); /* * OUTPUT: * array(3) { * ["name"]=> * string(10) "example_db" * ["username"]=> * string(6) "dbuser" * ["password"]=> * string(6) "dbpass" * } */
配置服务
另一个功能是通过配置添加服务到您的容器。默认情况下,这是通过在配置中的 di
键下添加一个 services
键来完成的,格式如下
$config = [ 'di' => [ 'services' => [ 'logger' => [ 'class' => Logger::class, 'singleton' => true, 'arguments' => [ StdoutLogger::class, ], 'methods' => [ 'setLogLevel' => [ 'info' ], ], ], StdoutLogger::class => [], ], ], ]; $container = new Container(); Configurator::apply()->configFromArray($config)->to($container); $logger = $container->get('logger'));
服务别名
您可以通过使用 service
关键字而不是 class
来创建另一个服务的别名。
$config = [ 'database' => [ /* ... */ ], 'di' => [ 'services' => [ DatabaseConnection::class => [ 'service' => MySQLDatabaseConnection::class, ], MySQLDatabaseConnection::class => [ 'arguments' => [ 'config.database.host', 'config.database.username', 'config.database.password', 'config.database.dbname', ], ], ], ], ];
服务工厂
如果您在创建服务时需要一些额外的逻辑,您可以定义一个服务工厂。服务工厂是一个可调用的类,可以接受一系列参数并返回服务实例。
通过使用 factory
键而不是 class
键将服务添加到容器中。
示例配置
$appConfig = [ 'db' => [ 'host' => 'localhost', 'database' => 'example_db', 'username' => 'example_user', 'password' => 'example_password', ], 'di' => [ 'services' => [ 'database' => [ 'factory' => MySQLPDOFactory::class, 'singleton' => true, 'arguments' => [ 'config.db.host', 'config.db.database', 'config.db.username', 'config.db.password', ], ], ], ], ];
示例服务工厂
<?php class MySQLPDOFactory { public function __invoke($host, $database, $username, $password) { $dsn = "mysql:host=$host;dbname=$database"; $pdo = new PDO($dsn, $username, $password); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); return $pdo; } }
注入容器
在极少数情况下,如果您想将容器作为依赖项注入到您的某个服务中,可以使用 Configurator::container()
作为注入依赖的名称。这只能在 PHP 配置文件中使用,YAML 或 JSON 中不可用。
$config = [ 'di' => [ 'services' => [ ContainerAwareService::class => [ 'arguments' => [Configurator::container()], ], ], ], ];
配置词法分析器
您还可以通过在配置的 di
部分添加 inflectors
键来设置 词法分析器。
$appConfig = [ 'di' => [ 'inflectors' => [ LoggerAwareInterface::class => [ 'setLogger' => ['Some\Logger'] ], ], ], ];
额外设置
可以通过使用 withSetting(string $name, $value)
方法调整 Configurator
的行为
Configurator::apply() ->configFromFiles('*.cfg.php'), ->withSetting(Configurator::SETTING_PREFIX, 'settings') ->withSetting(Configurator::SETTING_SEPARATOR, '/') ->to($container);
可用设置有
名称 | 描述 | 默认值 |
---|---|---|
SETTING_PREFIX | 设置配置值键的前缀名称。 | config |
SETTING_SEPARATOR | 设置配置键的分隔符。 | . |
SETTING_SERVICES_KEY | 服务配置的位置。 | di.services |
SETTING_INFLECTORS_KEY | 词法分析器配置的位置。 | di.inflectors |
SETTING_DEFAULT_SINGLETON_SERVICES | 设置服务是否默认为单例。 | false |
高级定制
添加自定义文件读取器
您可以通过实现 TomPHP\ContainerConfigurator\FileReader\FileReader
接口来创建自己的自定义文件读取器。创建后,可以使用 withFileReader(string $extension, string $readerClassName)
方法来启用它。
重要:withFileReader()
必须在调用 configFromFile()
或 configFromFiles()
之前调用!
Configurator::apply() ->withFileReader('.xml', MyCustomXMLFileReader::class) ->configFromFile('config.xml'), ->to($container);
添加自定义容器适配器
您可以通过实现 TomPHP\ContainerConfigurator\FileReader\ContainerAdapter
接口来创建自己的容器适配器,以便配置其他容器。创建适配器后,可以使用 withContainerAdapter(string $containerName, string $adapterName)
方法来启用它。
Configurator::apply() ->withContainerAdapter(MyContainer::class, MyContainerAdapter::class) ->configFromArray($appConfig), ->to($container);