在Symfony编译器通行证中读取捆绑包配置
#网络开发人员 #php #tip #symfony

创建Symfony Bundle时,您通常需要使用自定义的Configuration来配置或什至在服务容器的编译过程中添加各种服务。 Symfony通过实现Extension提供了此选项。虽然Extension提供了很多这样做的选项,但大型配置可以轻松创建一个大型扩展类,该类的作用太多了。

这种方法的替代方法是使用编译器通过将所有逻辑分为单独的步骤。但是,一个很大的缺点是,默认情况下,这些编译器通过无法访问最终编译配置。

要解决这个问题,经常使用的解决方案是将配置存储在服务容器上的临时瞬态参数中。因为编译器通行证可以访问容器的(副本),因此您可以在编译完成之前读取该参数并将其从容器中删除。

尽管这是一个可行的选择,但这些临时值的使用似乎总是有点不合时宜。再加上开发人员必须非常意识到之后删除值。让我们看一下将这种配置提供给编译器通过的绝佳替代选择。

将扩展名注入编译器通过

由于Extension 位置,其中该捆绑包的配置是汇总和组合的,因此它应作为配置的唯一值得信赖的来源。这意味着我们只能从扩展类中检索配置。

幸运的是;您可以在捆绑类别的build()方法中初始化并添加编译器通行证。此类还可以使用getContainerExtension()方法访问扩展名。这意味着我们可以注入
这样的延伸到我们的编译器通行证:

use Symfony\Component\HttpKernel\Bundle\Bundle;

final class MyEpicBundle extends Bundle
{
    public function build(ContainerBuilder $container): void  
    {  
        $extension = $this->getContainerExtension();

        if ($extension instanceof MyEpicExtension) {
            $container->addCompilerPass(new MyEpicCompilerPass($extension));
        }
    }
}

要接受编译器通行证中的扩展名,我们需要确保将其作为第一个参数:

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;

final class MyEpicCompilerPass implements CompilerPassInterface
{  
    public function __construct(private MyEpicExtension $extension)  
    {
    }

    public function process(ContainerBuilder $container): void  
    {  
        // ... We want our configuration here.
    }
}

从扩展程序中检索配置

扩展名具有实现一个接收所有提供的配置的load()方法(例如,从项目或其他需要配置此捆绑包的捆绑包中)以及容器的副本。要将所有这些配置汇编为最终配置阵列,您可以使用Processor,或者如果扩展了base Extension

,请使用Extension::processConfiguration()方法。

无论哪种情况,您都可能希望避免多次处理配置;因此,让我们添加一个包含编译配置的微型缓存,仅检索。

use Symfony\Component\DependencyInjection\Extension\Extension;

final class MyEpicExtension extends Extension
{
    private array $config;

    public function load(array $configs, ContainerBuilder $contaienr): void
    {
        $loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/../../config'));
        $loader->load('services.yaml');  

        $this->compileConfig($configs);
    }

    /**
     * Compiles and stores the configuration once.
     */
    private function compileConfig(array $configs): void  
    {  
        $configuration = new Configuration(); // This is our bundle's configuration class.
        $this->config ??= $this->processConfiguration($configuration, $configs);  
    }  

    /**  
     * Retrieves the configuration for the bundle.
     */
    public function getConfig(): array  
    {  
        return $this->config ?? [];  
    }
}

现在,我们能够通过在扩展程序上调用getConfig()方法来检索编译器通过中的整个捆绑包配置。

// MyEpicCompilerPass.php
public function process(ContainerBuilder $container): void  
{  
    $config = $this->extension->getConfig();

    // ...
}

实际上是在编译器通行证中完成的。这称为合并通行证,是first compiler pass to be processed。因此,一旦我们的自定义编译器通行证读取了关闭扩展的配置,我们就可以确定它已经被编译,缓存并准备好使用。

就是这样

正如我所说的;在编译器通行证内使用配置还有其他方法。在某些情况下,甚至不需要编译器通行证。很小的配置很可能会在捆绑扩展程序内处理。像往常一样“取决于”;但这也是一件好事。

我希望您喜欢阅读这篇文章!如果是这样,请留下ð反应或兼评论,并考虑订阅我的新闻通讯!您也可以在ð上关注我twitter,以获取更多内容和偶尔的提示。