找出/自定义 Symfony Forms Twig 块名称

Find out / customize Symfony Forms Twig block name

我想覆盖我的表单部分的呈现方式,但我总是忘记 symfony 表单呈现的是哪个 twig 块名称。如果找不到该块,我不会得到任何反馈,为什么找不到,以及应该如何调用它。

示例:

class SetPasswordType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('plainPassword', PasswordType::class);
        $builder->add('repeatPlainPassword', PasswordType::class);
    }
}

三个基本问题:

对于这种特定类型,树枝 widget 块名称是 set_password_widget

像这样在您的表单主题中覆盖它:

{% block set_password_widget %}
    <div class="row">
        <div class="col">
            {{ form_row(form.plainPassword) }}
        </div>
        <div class="col">
            {{ form_row(form.repeatPlainPassword) }}
        </div>
    </div>
{% endblock %}

如何覆盖块

  • 确定块前缀,默认情况下取决于 class 名称。对于 SetPasswordType,它是 set_password
  • 决定要渲染哪个块。如果您想更改布局,您可能会覆盖 row 块。如果您想更改输入,您可能会覆盖 widget 块。参考文档:https://symfony.com/doc/current/form/form_themes.html#form-fragment-naming
  • 将方块前缀和方块名称连接在一起。对于 SetPasswordTypewidget 块,您想覆盖 set_password_widget.
  • 将树枝块放在您的表单主题中。

覆盖失败时进行故障排除

  • 检查 twig 块是否在 twig.form_themes 中配置的文件中,或者以其他方式包含在表单主题中。
  • 检查 Symfony\Component\Form\Extension\Core\Type\BaseType::buildView 中的 $blockPrefixes 以查看确定了哪些块前缀。将首先查找数组中的最后一个条目。
  • 检查 $blockNameHierarchy in Symfony\Component\Form\FormRenderer::searchAndRenderBlock 以查看查找了哪些特定块。将首先查找数组中的最后一个条目。

详细演练

块的名称在 Symfony\Component\Form\Extension\Core\Type\BaseType::buildView 中建立,在 $blockPrefixes 变量中。 $blockPrefixes 定义了以下优先级(首先提到的 = 最高优先级。它是反向存储的!):

  • 唯一的块名称(基于 属性 名称分层构建)。
  • 块前缀,如果已配置
  • 类型的名称(如果继承自AbstractType,名称在AbstractType::getBlockPrefix()中生成)
  • 所有父类型的名称(在 FormTypeInterface::getParent() 方法链之后)。

例如,它可能看起来像这样:

$blockPrefixes = [
  0 => "form", # because `AbstractType::getParent()` returns `FormType`
  1 => "set_password", # our type, name resolved automatically depending on class name 

  ## at this position, a block prefix would be included if one is configured 

  2 => "_set_password" # the hierarchical unique name, prefixed with `_`. for the plainPassword field, this value would be "searchAndRenderBlock". 
];

当表单由 twig 呈现时,Symfony\Component\Form\FormRenderer::searchAndRenderBlock 会调用相应的 $blockNameSuffix(例如 widgetrow)。 $blockNameHierarchy 是通过在每个可能的前缀后缀 $blockNameSuffix.

创建的

对于 $blockNameSuffix == "row" 它看起来像这样:

$blockNameHierarchy = [
  0 => "form_widget",
  1 => "set_password_widget",
  2 => "_set_password_widget"];

查找这些块,选择能找到的优先级最高的块。数组越靠后,优先级越高。

自定义块前缀

您可以像这样自定义前缀:

class SetPasswordType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('plainPassword', PasswordType::class, ['mapped' => false]);
        $builder->add('repeatPlainPassword', PasswordType::class, ['mapped' => false]);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefault('block_prefix', 'my_custom_prefix');
        $resolver->setDefault('block_name', 'my_custom_name');
    }
}

这将导致

$blockPrefixes = [
  0 => "form", 
  1 => "set_password", # this will stay the same as its resolved depending on type name

  2 => "my_custom_prefix", # as per our configuration, we now have a custom prefix

  3 => "_my_custom_name" # the custom name will be used to determine the hierarchical name
];