dhii / containers
精选的PSR-11容器,具有实用性、简洁性和易用性。
v0.2.0-alpha1
2024-09-21 22:38 UTC
Requires
- php: ^7.4 | ^8.0
- container-interop/service-provider: ^0.4
- dhii/collections-interface: ^0.4.0-alpha2
Requires (Dev)
- gmazzap/andrew: ^1.1
- phpunit/phpunit: ^9.0
- psr/container: ^2.0
- psr/simple-cache: ^1.0
- slevomat/coding-standard: ^6.0
- vimeo/psalm: ^5.0
- wildwolf/psr-memory-cache: ^1.0
- 0.2.x-dev
- v0.2.0-alpha1
- 0.1.x-dev
- v0.1.5
- v0.1.4
- v0.1.4-alpha2
- v0.1.4-alpha1
- v0.1.3-alpha2
- v0.1.3-alpha1
- v0.1.2
- v0.1.2-alpha1
- v0.1.1
- v0.1.1-alpha1
- v0.1.0-alpha1
- dev-revert-29-feature/upgrade-container-interop
- dev-feature/upgrade-container-interop
- dev-recursive-detection
- dev-master
- dev-task/segmenting-map
- dev-release/0.1.2
This package is auto-updated.
Last update: 2024-09-21 22:39:42 UTC
README
详细信息
精选PSR-11容器,具有实用性、简洁性和易用性。
通用
CachingContainer
- 一个装饰器,将缓存的关注点分离,允许缓存任何容器的值。CompositeContainer
- 一个由多个其他容器组成的容器。在键访问时,遍历其内部容器列表,并访问具有该键的第一个容器的该键。当需要从多个来源合并配置而不实际进行合并时很有用。ProxyContainer
- 一个将访问转发到1个其他容器的容器,该容器可以在构造后分配。当需要解决与容器相关的递归依赖问题,例如查找委派时很有用。AliasingContainer
- 一个装饰器,通过别名键提供对另一个容器的访问。当需要将不可变映射的键更改时很有用。MappingContainer
- 一个装饰器,使用回调在飞行中操作从另一个容器检索的值。PrefixingContainer
- 一个装饰器,允许通过前缀键访问另一个容器的值。也可以回退到非前缀键。当需要在键上强制执行前缀命名约定时很有用。与DeprefixingContainer
相反。DeprefixingContainer
- 一个装饰器,允许访问具有前缀键的其他容器的值(无前缀)。例如,当需要简化遵循前缀命名约定的键时很有用。与PrefixingContainer
相反。MaskingContainer
- 一个装饰器,可以选择性地隐藏或显示另一个容器的键。当与具有定义结构的映射一起工作时很有用。PathContainer
- 一个装饰器,允许通过类似于路径的键访问嵌套容器的层次结构。当需要访问从多个来源合并的配置时很有用。SegmentingContainer
- 一个装饰器,允许将分隔符分隔的路径样式的键作为容器层次结构访问。当在键上使用类似于路径的命名约定(如命名空间)时,可用于隔离配置段。与PathContainer
相反。HierarchyContainer
- 一个容器,允许将任意数组的层次结构作为容器层次结构访问。在原地创建容器,并为其未来的重复使用进行缓存。Dictionary
- 通过容器接口访问数组,同时不牺牲迭代性。DataStructureBasedFactory
允许对任意深度的数组层次结构进行递归。将数组转换为容器时特别有用,尤其是与其他装饰器一起使用。SimpleCacheContainer
- 一个装饰器,将 PSR-16 缓存呈现为一个可变、可清除的容器,具有固定 TTL。FlashContainer
- 一个装饰器,将内部存储容器中的值呈现为另一个容器,将该值复制到内存中,然后从存储中清除。NoOpContainer
- 一个无操作的可写可变可清除映射,不执行任何操作,并且不能有任何值。
DI
ServiceProvider
- 一个非常简单的实现,允许快速从已知工厂和扩展的映射中创建 服务提供者。CompositeCachingServiceProvider
- 一个服务提供者,聚合其他服务提供者的工厂和扩展。聚合的结果将被缓存,这意味着它最多只执行一次实例 - 当检索这些工厂或扩展时。TaggingServiceProvider
- 一个服务提供者,将标记服务聚合到具有标记名称的服务中。DelegatingContainer
- 一个容器,在返回值之前将调用其配置的服务提供者的工厂和扩展。如果指定了父容器,则将传递给服务定义而不是此容器。这允许 依赖项查找委托,这在从其他容器组合容器时特别有用。
示例
应用程序容器
大多数现代应用程序都使用某种类型的 DI 容器配置。以下示例演示了一个用例,其中所有配置都由不同的源组成,通过单个真实来源访问,每个请求都缓存服务。
// 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');
服务标记
您可以将服务标记到集合中。这将添加一个具有相同名称的服务,该服务将返回具有该标记的服务列表。
由于服务名称在理论上可以是任何合法字符串,但为了使其成为标记,需要对其设置一些限制,因此标记名称可以包含除空白以外的任何字符(任何与 \s
匹配的字符)。
[ 'serviceA' => /** @tag letters */ fn (): string => 'A', 'serviceB' => /** * @tag letters */ function (): string { return 'B'; }, 'serviceC' => function (ContainerInterface $c): string { var_dump($c->get('letters')); }, ];
以上示例的结果如下 var_dump()
array(2) {
[0]=>
string(1) "A"
[1]=>
string(1) "B"
}
关于映射的有趣事情
映射在应用程序中非常常用,用于表示某些键值关系。我们决定 PSR-11 容器是表示映射的互操作方式的好方法。以下是您可以做的事情。
// 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