Compiler passes是Symfony提供的“在程序被执行之前容器被编译时”操作服务定义的一种架构。
Compiler Pass优先级 ¶
容器被编译的过程是复杂的,它分为若干步骤,被称为“优化传递(optimization passes)”(如解析服务引用等)和“删除传递”(如删除无用的服务)。
当注册一个compiler pass时,你可以选择其“发生阶段”,这得益于addCompilerPass()
方法的第二个可选参数:
1 2 | // ...
$container->addCompilerPass(new CustomPass(), PassConfig::TYPE_AFTER_REMOVING); |
但是,你却不能选择在当前的“容器编译阶段”,Compiler Pass的执行顺序,所以只能是按“Symfony先发现谁”来排序。在某些情况下,这是不被接受的,所以Symfony 3.2允许你设置Compiler Pass优先级。
优先级被定义在addCompilerPass()
方法的第三个参数。默认的优先级是0
,这个值可以是任何正负整数。愈高的优先级,愈先被执行:
1 2 | // ...
$container->addCompilerPass(new CustomPass(), PassConfig::TYPE_AFTER_REMOVING, 30); |
找到打了标签的服务并对其排序 ¶
Contributed by
Iltar van der Berg
in #18482.
Compiler Pass的一个常见需求是,找到每一个打了给定标签的服务,然后按其优先级来排序。Symfony框架本身的代码库中,某些部分就要用到这个功能,因此Symfony 3.2添加了一个trait,用于找到标签服务,并对其排序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // Before Symfony 3.2
class CustomPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$warmers = array();
foreach ($container->findTaggedServiceIds('kernel.cache_warmer') as $id => $attributes) {
$priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
$warmers[$priority][] = new Reference($id);
}
krsort($warmers);
$warmers = call_user_func_array('array_merge', $warmers);
// ...
}
} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // In Symfony 3.2
use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
class CustomPass implements CompilerPassInterface
{
use PriorityTaggedServiceTrait;
public function process(ContainerBuilder $container)
{
$warmers = $this->findAndSortTaggedServices('kernel.cache_warmer', $container);
// ...
}
} |