在具有循环关系

时间:2018-02-02 16:48:38

标签: typo3 extbase

我正在尝试使用CMS 8.7.9创建嵌套表单,以允许前端中的IRRE。 提交此表单时,如果存在指向1:n关系的记录指向返回根对象,则我会看到已提交的表单数据的验证被跳过。

我有这样的域名模型:

class RootObject extends AbstractEntity {
   /**
    * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\Vendor\Ext\Domain\Model\Child>
    * @cascade remove
    */
   protected $children = null;

   /**
    * @var \Vendor\Ext\Domain\Model\OtherObject
    * @validate NotEmpty
    */
   protected $otherProperty = null;
   ...
}
class Child extends AbstractEntity {
   /**
    * @var \Vendor\Ext\Domain\Model\RootObject
    */
   protected $parent = null;

   /**
    * @var string
    */
   protected $title = '';
   ...
}

由ExtensionBuilder创建的TCA配置,inline用于1:n关系,passthrough在子节点上,指向rootObject。

应该可以在一个表单中创建和编辑RootObject及其子项。我的流体模板看起来像:

<f:form method="post" controller="RootController" action="update" name="rootObject object="{rootObject}">
    <f:form.select property="otherProperty"/>
    <f:for each="{rootObject.children}" as="child iteration="iter">
            <f:form.textfield type="text" property="children.{iter.index}.title"/>
    </f:for>
    ...
</f:form>

当我为RootObject提交此表单而没有Child时,$otherProperty的NotEmpty验证已正确评估,并且我收到相应的验证错误。但是,只要RootObject在关系中有Child,就不会评估otherProperty的验证。

我将其跟踪到\TYPO3\CMS\Extbase\Validation\Validator\GenericObjectValidator,其中validate重置了验证结果。

我不完全理解为什么 - 但是在验证rootObject extbase调用Child的验证器时,又会再次调用rootObject验证重用验证器实例当前正在验证调用树的rootObject。然后它会覆盖当前的$result

修补该行
- $this->result = new \TYPO3\CMS\Extbase\Error\Result();
+ $this->result = $this->result ?: new \TYPO3\CMS\Extbase\Error\Result();

解决了这个问题。

我是否使用嵌套表单错误,或者这是一个Extbase错误?

修改 有关验证调用树的更多见解: ConjunctionValidator($rootObject)来电 GenericObjectValidator($rootObject->children)来电 CollectionValidator($rootObject->children)来电 ConjunctionValidator($child)来电 GenericObjectValidator($child->parent)来电 与我们开始时相同的ConjunctionValidator实例。这导致覆盖在下降到验证$rootObject->children之前生成的验证结果。

1 个答案:

答案 0 :(得分:0)

尝试在您的控制器中执行以下操作:

public function initializeUpdateAction()
{
    if ($this->arguments->hasArgument('rootObject')) {
        $this->arguments->getArgument('rootObject')
            ->getPropertyMappingConfiguration()
            ->forProperty('children.*')
            ->skipProperties('parent');
    }
}

初始化操作在您的操作之前和验证之前运行。

首先我们检查一下我们是否有参数。然后我们获取参数rootObject的属性映射配置,并告诉它不要验证children.*.parent,因为它已经过验证。

它是未经测试的,并且是从记忆中写出的,但希望它可以帮助你。