【问题标题】:Extbase validation skipped on nested form with circular relationship在具有循环关系的嵌套表单上跳过 Extbase 验证
【发布时间】:2018-07-13 05:27:33
【问题描述】:

我正在尝试使用 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>

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

我追踪到\TYPO3\CMS\Extbase\Validation\Validator\GenericObjectValidatorvalidate 重置验证结果。

我不完全理解为什么 - 但是当验证 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-&gt;children) 来电 CollectionValidator($rootObject-&gt;children) 来电 ConjunctionValidator($child) 来电 GenericObjectValidator($child-&gt;parent) 来电 与我们开始时相同的ConjunctionValidator 实例。这会导致覆盖在下降到验证 $rootObject-&gt;children 之前生成的验证结果。

【问题讨论】:

    标签: typo3 extbase


    【解决方案1】:

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

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

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

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

    它未经测试并且是凭记忆编写的,但希望对您有所帮助。

    【讨论】:

    • 我不知道skipProperties,看起来很有希望-谢谢!。但是路径符号和通配符匹配在那里不起作用。使用$this-&gt;arguments-&gt;getArgument('rootObject')-&gt;getPropertyMappingConfiguration()-&gt;getConfigurationFor('children') 我可以获得ObjectStorage 的配置。如果我知道他们的索引,就可以访问孩子 - 没有找到遍历所有 $subConfigurationForProperty 的解决方案。所以我所需要的只是以某种方式进入 ObjectStorage。
    • 通过遍历$this-&gt;request-&gt;getArguments()['rootObject']['children'] 的键找到了一种方法。但是在调试时我发现甚至没有为parent 完成映射,因为表单中不存在该字段。所以错误必须位于其他地方。
    • 对不起。 skipProperties 需要属性名称,而不是属性路径。我已经用forProperty 更新了我上面的答案,它确实接受带有通配符的路径。 See implementation on github here
    • 我刚刚意识到您在 TCA 配置中为字段 parent 使用了 passthrough。就我个人而言,我不使用扩展构建器,而且我从未在要映射到域模型的字段上使用 passthrough。我认为您必须为parent 字段提供正确的groupselect TCA 配置才能使extbase 按预期工作。测试这是否是引入问题的字段的一种快速方法是简单地将其从模型中临时删除,刷新缓存,然后再次测试您的表单。如果现在验证正确,那么您就知道问题出在哪里了。
    • 对不起,沉默 - 不得不把它搁置一段时间。感谢您的进一步cmets。 passthrough 不是罪魁祸首,已经尝试使用 select。但是扩展生成器使用的是passthrough,这就是为什么我认为它是更不容易出错的设置。实际上,只要我在child 中没有parent 字段,它就可以验证正确。只要那在那里,验证就会被覆盖。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-31
    • 2021-08-12
    • 2010-09-24
    • 2016-06-11
    相关资源
    最近更新 更多