Symfony 2 - 在使用SonataAdminBundle保持验证的同时,从Admin更改实体的字段

时间:2014-08-05 09:09:31

标签: forms validation symfony doctrine-orm sonata-admin

使用: Symfony 2.5 SonataAdminBundle

我试图通过使用来自关联的entites的两个字段来提交/保存数据时,更改其中一个实体字段(标题)。

DocumentRevision< - Document - > CustomEntity [title] =文档[title] + DocumentRevision [number]

但是CustomEntity的标题必须是唯一的 - 这是我试图通过数据库约束和UniqueEntity验证来解决和管理的问题(不完全 - 稍后会详细介绍)。

现在问题是我更改了Doctrine preUpdate / Persist上的标题数据,有效地跳过了该字段的验证,因为它在验证时是空的。当用户输入错误数据时,数据库层会抛出有关唯一约束的重复错误。

/**
* @ORM\PrePersist
* @ORM\PreUpdate
*/
public function setTitleFromDocumentName() {
    $this->setTitle($this->getDocument()->getName() . " rev. " . $this->getDocumentRevision()->getRevisionNumber());
}

实体本身在字段title上使用UniqueEntity约束,因此自定义约束或验证组是我的观点,因为它只会复制已经使用的约束。

/**
 * @UniqueEntity(
 *      fields={"title"}
 * )
**/

最简单的解决方案似乎是在验证之前提交到提交之间,但必须从实体完成。

我的问题是如何(可以?)完成没有覆盖SonataCRUD控制器或它的其他部分,是否可能?

可以做到,但有问题:

我可以使用Form Events更改标题:

protected function configureFormFields(FormMapper $formMapper) {
...
$builder = $formMapper->getFormBuilder();
    $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
        $data = $event->getData();
        $form = $event->getForm();

        if (!$data) {
            return;
        }

        $data['title'] = $data['document'] . ' rev. ' . $data['documentRevision'];
        $event->setData($data);
    }
...
formMapper
        ->add('title',null,array(
...
);

目前的问题是,我正在获取'文件'的ID和' documentRevision'我至少需要他们的名字或__toString()表示。

另一个问题是虽然我可以使用该事件设置标题,但是当它应该显示表单错误时它会显示错误,因为验证应该在FormEvents::SUBMIT进行 - 这个我不会理解。

最后要注意的是,如果我尝试使用回调函数:

$builder->addEventListener(FormEvents::PRE_SUBMIT, array($this,'onPreSubmit'))

public function onPreSubmit() {
    $entity = $this->getSubject();
    $entity->setTitleFromDocumentName();
}

如果Entity尝试从相关的entites获取字段,我将获得空标题和错误 - 在非对象上调用函数。

2 个答案:

答案 0 :(得分:0)

关于实体数据,这可能会帮助您获得主题: https://gist.github.com/webdevilopers/fef9e296e77bb879d138

然后你可以使用getter来获取所需的数据:

protected function configureFormFields(FormMapper $formMapper)
{
    $subject = $this->getSubject();

    $formMapper->getFormBuilder()->addEventListener(FormEvents::PRE_SET_DATA,
        function (FormEvent $event) use ($subject) { 
            $document = $subject->getDocument();

            // ...
    });
}

我也在你的问题上贴了这个: https://github.com/sonata-project/SonataAdminBundle/issues/2273

答案 1 :(得分:0)

当我将唯一的实体验证约束更改为我从概念角度看不完全有效的约束时,解决了这个问题。

同样重要的是要注意标记为@PrePersist,@ PreUpdate等的函数必须是公共的,如果要像这样使用它们,将它们标记为私有将使Doctrine失败。

  

请注意,设置为生命周期回调的方法需要是公共的,并且在使用这些注释时,您必须在实体类上应用@HasLifecycleCallbacks标记注释。

     

请参阅:http://doctrine-orm.readthedocs.org/en/latest/reference/events.html#lifecycle-callbacks(代码示例后的第一段)。