创建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,以获取更多内容和偶尔的提示。