Extbase:使同一页面上的两个表单修改相同 object 具有单独的验证错误和用户输入

Extbase: Make two forms on a same page modifying same object have separate validation errors and user input

我有一个 Parent object,它有一个 $children 属性 类型的 ObjectStorage,其中包含 collection 的 Child objects.

页面包含两个 Fluid 形式,指向同一个 saveAction(),第一个形式是否接受 file-upload (CSV-file) for $children 属性,第二种形式接受输入列表。

简化后看起来像这样:

<f:form action="save" name="parent" object="{parent}" enctype="multipart/form-data">
    <f:form.validationResults for="parent">
    error output
    </f:form.validationResults>
    <f:form.upload property="children" />
    <f:form.submit />
</f:form>

<f:form action="save" name="parent" object="{parent}">
    <f:form.validationResults for="parent">
    error output
    </f:form.validationResults>
    <f:form.textfield property="children.0.title" />
    <f:form.textfield property="children.1.title" />
    <f:form.textfield property="children.2.title" />
    <f:form.textfield property="children.3.title" />
    <f:form.textfield property="children.4.title" />
    <f:form.submit />
</f:form>

两种形式都在为 parent.

创建 child objects

除了出现验证错误(文件格式错误,child 的标题不正确等)的情况外,一切正常。然后验证错误会以两种形式显示,无论是从哪一个提交的。来自 CSV-file 的已解析标题也显示在第二种形式的输入中。

我可以看出其中的原因:请求参数 parent 取自表单的名称,并且两者都相同。但是,如果我以其中一种形式重命名它,属性Mapper 将不再找到将重命名的 属性 映射到的动作变量。

我发现,属性 映射配置允许为属性设置映射,所以我将 <f:form.upload property="children" /> 更改为 <f:form.upload property="childrenFile" />,然后在 initializeSaveAction():

$this->arguments['parent']
    ->getPropertyMappingConfiguration()
    ->setMapping('childrenFile', 'children');

但它只是帮助属性 Mapper识别目标属性名称,所有验证结果仍然显示在<f:form.validationResults for="parent.children">下,而不是在parent.childrenFile下显示为我很期待。

我现在看到的唯一肮脏的解决方案是使用不同的参数名称进行两个不同的操作(以及不同形式的 name 属性),但实际上它们在做同样的事情。

这在简单的情况下解决了一个问题,但在更复杂的情况下(例如,依赖参数总是被命名为 parent 并有一个基于它的逻辑,比如访问检查)它变得复杂并且看起来仍然就像一个肮脏的解决方案。

有解决这个问题的干净方法吗?

重命名一个表单的对象和动作,然后您可以单独访问验证错误。

<f:form action="saveUpload" name="uploadParent" object="{parent}" enctype="multipart/form-data">
    <f:form.validationResults for="uploadParent">
    error output
    </f:form.validationResults>
    <f:form.upload property="children" />
    <f:form.submit />
</f:form>

<f:form action="save" name="parent" object="{parent}">
    <f:form.validationResults for="parent">
    error output
    </f:form.validationResults>
    <f:form.textfield property="children.0.title" />
    <f:form.textfield property="children.1.title" />
    <f:form.textfield property="children.2.title" />
    <f:form.textfield property="children.3.title" />
    <f:form.textfield property="children.4.title" />
    <f:form.submit />
</f:form>

现在你需要一个新动作:

protected function saveUploadAction(Object $uploadParent) {
  $this->forward('save', NULL, NULL, array('parent' => $uploadParent));
}

当然:你的验证也应该在新的 saveUploadAction 中,所以错误来自于转发之前的第一个动作。