将深层嵌套的property_path映射到父窗体

时间:2013-09-11 03:40:31

标签: forms symfony

我正在Symfony 2中构建一个表单,其字段将根据相应实体的配置方式而有所不同。

简而言之,每个实体都有一组“详细信息”字段,可以包含不同类型和配置的数据。

例如,Project实体可能具有以下配置:

  • url呈现为文字输入,并验证为最长为300个字符的网址。
  • description呈现为没有验证限制的textarea。
  • logo呈现为文件输入并验证为最大尺寸为500x500的图像文件。

等等。使这一点变得有趣的部分是所有这些都是通过数据库表配置的,以便管理员可以通过UI更改这些模型的配置。

数据库结构的(相关部分)看起来像这样:

ERD showing 4 tables - project, project_detail, detail_type and detail_type_assignment

  • project存储项目记录。
  • project_detail存储每个项目的每个详细信息字段的值。
  • detail_type定义每个详细信息字段的类型和配置。
  • detail_type_assignment定义了每个实体可用的详细信息类型以及字段应在表单上显示的顺序。

到目前为止,除了在表单中呈现错误消息外,一切都运行良好。

当任何这些详细信息字段生成验证错误时,它将显示在表单的顶部:

Screenshot of project edit form with detail field error messages displayed at the top.

请注意,在上图中,“EIN”是存在于Project实体中的字段(即,实现了Symfony表单的常规方式),而“URL”和“徽标上传”则实现为细节领域。

以下是ProjectType的样子:

class ProjectType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name')
            ->add('ein', 'ein')
        ;

        /* Add detail fields to the form builder. */
        foreach($this->getDetailTypes() as $detailType)
        {
            $slug       = $detailType->getSlug();
            $formatter  = $detailType->createFormatterInstance('');

            $builder->add(
                  $slug
                , $formatter->getFormFieldType()
                , $formatter->getFormFieldOptions()
            );

            /* E.g.,
             *
             * $builder->add(
             *     'url'
             *   , 'text'
             *   , array('label' => 'URL', ...)
             * )
             */
        }
    }

    ...
}

我很确定这里发生的是ViolationMapper无法正确翻译property_path

例如,在运行时,property_path值的urlproject.details[url].value,但该字段位于project.url

我不想构建复杂的表单层次结构,以便每个字段的位置与其property_path匹配。有没有办法可以更改ExecutionContext中添加违规行为的路径?

1 个答案:

答案 0 :(得分:0)

在您看来,我觉得您不应该在form(form)form_start(form)内使用form_end(form)。我相信会生成两次<form>代码

旧回答:

Idk您的树枝看起来像什么,但我假设某种形式的行中的错误没有显示。 http://symfony.com/doc/current/book/forms.html#rendering-a-form-in-a-template谈论它。

从链接:

{# src/Acme/TaskBundle/Resources/views/Default/new.html.twig #}
{{ form_start(form) }}
{{ form_errors(form) }}

{{ form_row(form.task) }}
{{ form_row(form.dueDate) }}
{{ form_end(form) }}

Take a look at each part:
form_start(form) - Renders the start tag of the form.
form_errors(form) - Renders any errors global to the whole form (field-specific errors are displayed next to each field);
form_row(form.dueDate) - Renders the label, any errors, and the HTML form widget for the given field (e.g. dueDate) inside, by default, a div element;
form_end() - Renders the end tag of the form and any fields that have not yet been rendered. This is useful for rendering hidden fields and taking advantage of the automatic CSRF Protection.

form_row可以分成每个部分:

<div>
    {{ form_label(form.task) }}
    {{ form_errors(form.task) }}
    {{ form_widget(form.task) }}
</div>

并且form_errors()函数应显示您想要的内容。