paysera/lib-dependency-injection

为Symfony依赖注入组件提供辅助类

1.4.0 2023-11-24 12:04 UTC

This package is auto-updated.

Last update: 2024-09-24 14:03:52 UTC


README

Latest Version on Packagist Software License Build Status Coverage Status Quality Score Total Downloads

这是什么?

为简化与Symfony依赖注入组件的集成提供额外功能。

包含用于注册带有标签的服务以及某些其他服务的编译器传递 - 无需在每种情况下都编写自定义类。

安装

composer require paysera/lib-dependency-injection

基本功能

将带有标签的服务注册到其他服务。可选地传递标签的属性。

class SomeBundle extends Bundle
{
    public function build(ContainerBuilder $container)
    {
        $container->addCompilerPass(new AddTaggedCompilerPass(
            'some_bundle.registry', // ID of service to modify
            'my_provider',          // name of tag to search for
            'addProvider',          // method to call on modified service
            [           // this parameter is optional and defines attributes to pass from tag
                'key',
                'theme' => 'default',   // attribute with default value
                'optional',
            ]
        ));
    }
}
class Registry
{
    // first - tagged service. Others (optional) in the order as they come in the attributes array
    public function addProvider(ProviderInterface $provider, $key, $theme, $optional = null)
    {
        $this->providers[$key] = $provider;    // or whatever
    }
}
<service id="some_bundle.registry" class="Acme\Registry">
    <argument>Any arguments service might have</argument>
    
    <!-- Such comment is optional here, but highly recommended for easier debugging: -->
    <!-- Calls addProvider with each service tagged with my_provider -->
</service>

<service id="awesome_provider" class="Acme\AwesomeProvider">
    <tag name="my_provider" key="awesome"/>
</service>
<service id="nice_provider" class="Acme\NiceProvider">
    <tag name="my_provider" key="nice" theme="not a default one"/>
</service>
<service id="superb_provider" class="Acme\SuperbProvider">
    <tag name="my_provider" key="superb" optional="leave theme as default, overwrite optional"/>
    <!-- Same service can have several tags, method will be called for each one of them -->
    <tag name="my_provider" key="superb_dark" theme="dark"/>
</service>

使用优先级

有时我们需要通过预定义的优先级调用带有标签的服务的方法。我们可以在服务本身中进行优先级排序,但这会使代码重复,并且不如编译时排序快 - 在运行时不需要对任何东西进行排序。

在注册编译器传递时应该启用优先级。它通过 priority 属性提供。优先级越低,调用越早。如果没有提供优先级,则默认为 0

class SomeBundle extends Bundle
{
    public function build(ContainerBuilder $container)
    {
        $container->addCompilerPass((new AddTaggedCompilerPass(
            'some_bundle.registry', // ID of service to modify
            'my_provider',          // name of tag to search for
            'addProvider',          // method to call on modified service
            ['key', 'theme' => 'default', 'optional'],
        ))->enablePriority()); // attribute name can be passed here, defaults to `priority`
    }
}
<service id="awesome_provider" class="Acme/AwesomeProvider">
    <tag name="my_provider" key="awesome"/>
</service>
<service id="nice_provider" class="Acme/NiceProvider">
    <tag name="my_provider" key="nice" priority="-1" theme="dark"/>
    <tag name="my_provider" key="fallback" priority="9001" optional="optional param"/>
</service>
<service id="another_provider" class="Acme/AnotherProvider">
    <tag name="my_provider" key="another"/>
</service>

解析为

// priority -1 - smallest:
$registry->addProvider($niceProvider, 'nice', 'dark');
// priority defaults to 0, called in the order as registered:
$registry->addProvider($awesomeProvider, 'awesome', 'default');  
$registry->addProvider($anotherProvider, 'another', 'default');
// priority is over 9000:
$registry->addProvider($awesomeProvider, 'fallback', 'default', 'optional param');

调整性能

当通过方法调用添加许多服务时,所有这些服务都需要在收集器服务实例化时创建。如果服务数量很多,这可能会变得麻烦。

这就是为什么你可以配置一些选项来使用,而不仅仅是传递服务

  • lazy_service - 正常传递服务,但标记所有服务为懒加载。在大多数情况下,这使生产环境更快,但在开发中可能会相当慢,因为每次修改这些服务(甚至是代码本身)时,容器都必须重建;
  • id - 仅传递服务的ID,同时使带有标签的服务公开。这要求你将 container 注入到收集器中,并在需要时通过ID获取服务。
class SomeBundle extends Bundle
{
    public function build(ContainerBuilder $container)
    {
        $container->addCompilerPass((new AddTaggedCompilerPass(
            'some_bundle.registry', // ID of service to modify
            'my_provider',          // name of tag to search for
            'addProvider',          // method to call on modified service
            ['key', 'theme' => 'default', 'optional'],
        ))->setCallMode(AddTaggedCompilerPass::CALL_MODE_ID));
    }
}
class Registry
{
    private $container;

    public function addProvider(string $providerId, $key, $theme, $optional = null)
    {
        $this->providers[$key] = $providerId;
    }
    
    private function getProvider(string $key)
    {
        return $this->container->get($this->providers[$key]);
    }
    
    // ...
}

语义版本控制

这个库遵循语义版本控制

有关API中可以更改和不能更改的基本信息的详细信息,请参阅Symfony BC规则

运行测试

composer update
composer test

贡献

请随意创建问题并提供拉取请求。

您可以使用以下命令修复任何代码风格问题

composer fix-cs