dhii/containers
Composer 安装命令:
composer require dhii/containers
包简介
A selection of PSR-11 containers for utility, simplicity, and ease.
关键字:
README 文档
README
Details
A selection of PSR-11 containers for utility, simplicity, and ease.
Generic
CachingContainer- A decorator that separates the concern of caching, allowing for caching of any container's values.CompositeContainer- A container that is composed of multiple other containers. On key access, iterates over its internal list of containers, and accesses that key of the first container which has that key. Useful for merging configuration from multiple sources, without actually doing any merging.ProxyContainer- A container that forwards access to 1 other container, which can be assigned after construction. Useful for solving container-related recursive dependency problems, for example for lookup delegation.AliasingContainer- A decorator that provides access to another container via aliased keys. Useful when an immutable map needs to have its keys changed.MappingContainer- A decorator that uses a callback to manipulate values retrieved from another container on the fly.PrefixingContainer- A decorator that allows access to another container's values via prefixed keys. Can also fall back to non-prefixed keys. Useful when e.g. enforcing a prefixing naming convention on keys. The opposite ofDeprefixingContainer.DeprefixingContainer- A decorator that allows access to another container's values that have prefixed keys - without the prefix. Useful for e.g. simplification of keys that follow a prefixiing naming convention. The opposite ofPrefixingContainer.MaskingContainer- A decorator that selectively hides or exposes keys of another container. Useful when working with maps that have a defined structure.PathContainer- A decorator that allows access to a hierarchy of nested container via path-like keys. Useful when accessing configuration merged from multiple sources.SegmentingContainer- A decorator that allows access to a container with delimiter-separated path-like keys as if it were a hierarchy of containers. Useful isolating a segment of configuration when using a path-like naming convention for keys (such as namespacing). The opposite ofPathContainer.HierarchyContainer- A container that allows access to a arbitrary hierarchy of arrays as if it was a hierarchy of containers. Creates containers in place, and caches them for future re-use.Dictionary- Allows access to an array via a container interface, without sacrificing iterability.DataStructureBasedFactoryallows this to be recursive for an array hierarchy of an arbitrary depth. Useful for transforming an array into a container, especially with other decorators.SimpleCacheContainer- A decorator that presents a PSR-16 cache as a mutable, clearable container with fixed TTL.FlashContainer- A decorator that presents a value from an inner storage container as another container, copying that value into memory, then clearing it from storage.NoOpContainer- A no-op writable mutable clearable map that does nothing, and cannot have any values.
DI
ServiceProvider- A super-simple implementation that allows quick creation of service providers from known maps of factories and extensions.CompositeCachingServiceProvider- A service provider that aggregates factories and extensions of other service providers. The results of this aggregation will be cached, meaing that it is only performed at most once per instance - when retrieving said factories or extensions.TaggingServiceProvider- A service provider that aggregates tagged services into a service with the tag's name.DelegatingContainer- A container that will invoke the factories and extensions of its configured service provider before returning values. If a parent container is specified, it will be passed to the service definitions instead of this container. This allows dependency lookup delegation, which is especially useful when composing a container out of other containers.
Examples
Application Container
Most modern applications use some kind of DI container setup. The below example demonstrates a use-case where all configuration is composed of different sources, accessible via a single source of truth, services are cached per request.
// Retrieve factories and extensions from respective files, and create a service provider with them $factories = require('factories.php'); $extensions = require('extensions.php'); $appProvider = new ServiceProvider($factories, $extensions); // Perhaps retrieve service providers from other modules and aggregate them $provider = new CompositeCachingServiceProvider([$appProvider, $moduleProviderA, $moduleProviderB]); $proxyContainer = new ProxyContainer(); // A temporary parent container for lookup delegation $container = new DelegatingContainer($provider, $proxyContainer); // Container with application configuration $appContainer = new CompositeContainer([ // The application's container $dbContainer, // <-- Perhaps another container with configuration from DB $container, // <-- The main container with merged configuration from modules ]); $appContainer = new CachingContainer($appContainer); // Add caching, so that each service definition is only invoked once $proxyContainer->setInnerContainer($appContainer); // Switch lookup to the application's main container, making it available in service definitions // Retrieve cached configuration aggregated from various modules and other sources, sucha as the database or a remote API $appContainer->get('my-service');
Service Tagging
You can tag your services into a collection. This adds a service with the same name as the tag, which will return a list of services tagged with it.
Since a service name can theoretically be any legal string,
while some limitations need to be set for it to remain a tag,
the tag name can contain any character besides whitespace (anything that matches \s).
[
'serviceA' =>
/** @tag letters */
fn (): string => 'A',
'serviceB' =>
/**
* @tag letters
*/
function (): string {
return 'B';
},
'serviceC' => function (ContainerInterface $c): string {
var_dump($c->get('letters'));
},
];
The above example results in the following var_dump():
array(2) {
[0]=>
string(1) "A"
[1]=>
string(1) "B"
}
Fun Things With Maps
Maps are very commonly used in applications to represent some key-value relationships. We decided that PSR-11 containers are a great way to represent maps in an interop way. Here are some of the things you can do.
// App configuration, perhaps from a file $config = [ 'dev' => [ 'db' => [ 'host' => 'localhost', 'username' => 'root', 'password' => '', 'database' => 'my_app', ], 'staging' => [ 'db' => [ 'host' => '123.abc.com', 'username' => 'application123', 'password' => '$*!@$T123SAfa', 'database' => 'my_app', ], ], ]; // Can create container hierarchies of arbitrary depths from array hierarchies $factory = new DataStructureBasedFactory(new DictionaryFactory()); // The new configuration interface $config = $factory->createContainerFromArray($config); // Output the DB host names for each environment foreach ($config as $env => $envConfig) { echo $env . ': ' . $envConfig->get('db')->get('host') . PHP_EOL; // Print 'dev: localhost' then 'staging: 123.abc.com' } // Access configuration using a path $config = new PathContainer($config, '/'); echo $config->get('staging/db/username'); // Print 'application123' // Access dev env DB config with a 'local_' prefix $localDbConfig = new PrefixingContainer($config->get('dev/db'), 'local_'); echo $localDbConfig->get('local_username'); // Print 'root' // Effectively adds production DB configuration $productionConfig = new Dictionary([ 'production' => [ 'db' => [ 'host' => 'db.myserver.com', 'username' => 'D97rh1d0A&13', 'password' => 'DN(Q(u3dgh3q87g3', 'database' => 'my_app', ], ], ]); $config = new CompositeContainer([$config, $productionConfig]); echo $config->get('production/db/password'); // Print 'DN(Q(u3dgh3q87g3' echo $config->get('dev/db/password'); // Print '': all of the old configuration is available on this new container // Make production host also available as 'live_db_host' - maybe something requires it to be at that key, and not in a path $config = new AliasingContainer($config, ['live_db_host' => 'production/db/host']); echo $config->get('live_db_host'); // Print 'db.myserver.com' echo $config->get('production/db/host'); // That value is still accessible by the original full path // Isolate production DB configuration, but without the 'password' key - perhaps to be passed to the UI, or another untrusted party $productionConfig = new MaskingContainer($config->get('production/db'), true, ['password' => false]); echo $productionConfig->get('password'); // NotFoundException: This key does not exist for this container
dhii/containers 适用场景与选型建议
dhii/containers 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 155.75k 次下载、GitHub Stars 达 9, 最近一次更新时间为 2019 年 05 月 09 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「container」 「PSR-11」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 dhii/containers 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 dhii/containers 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 dhii/containers 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Facilitates the routine step of bootstrapping PHP applications.
A fast and intuitive dependency injection container.
PSR-11 Aura.DI container configurator for Laminas and Mezzio applications. Drop-in replacement for the archived laminas/laminas-auradi-config with PHP 8.4 and 8.5 support.
Symfony compiler pass that allows to use service providers as defined in container-interop/service-provider
Dependency injection container for the Monolith framework.
The PSR-11 container bridges
统计信息
- 总下载量: 155.75k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 10
- 点击次数: 20
- 依赖项目数: 2
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2019-05-09