Forms Symfony 2-更改实体';在使用SonatAdminBundle保持验证的同时,从Admin获取s字段

Forms Symfony 2-更改实体';在使用SonatAdminBundle保持验证的同时,从Admin获取s字段,forms,validation,symfony,doctrine-orm,sonata-admin,Forms,Validation,Symfony,Doctrine Orm,Sonata Admin,使用: Symfony 2.5 索纳塔酒店 当数据被提交/保存到数据库时,我试图通过使用关联实体中的两个字段来更改其中一个实体字段(标题) DocumentRevision CustomEntity[标题]=文件[标题]+文件修订版[编号] 但CustomEntity的标题必须是唯一的——这是我试图解决的问题,并通过数据库约束和Uniquentity验证进行管理(不完全是——稍后将详细介绍) 现在的问题是,我更改了Doctrine preUpdate/Persist上的标题数据,有效地跳过了该字

使用: Symfony 2.5 索纳塔酒店

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

DocumentRevision CustomEntity[标题]=文件[标题]+文件修订版[编号]

但CustomEntity的标题必须是唯一的——这是我试图解决的问题,并通过数据库约束和Uniquentity验证进行管理(不完全是——稍后将详细介绍)

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

/**
* @ORM\PrePersist
* @ORM\PreUpdate
*/
public function setTitleFromDocumentName() {
    $this->setTitle($this->getDocument()->getName() . " rev. " . $this->getDocumentRevision()->getRevisionNumber());
}
/**
 * @UniqueEntity(
 *      fields={"title"}
 * )
**/
实体本身对字段
title
使用Uniquentity约束,因此自定义约束或验证组在我看来是点,因为它只会复制已使用的约束

/**
* @ORM\PrePersist
* @ORM\PreUpdate
*/
public function setTitleFromDocumentName() {
    $this->setTitle($this->getDocument()->getName() . " rev. " . $this->getDocumentRevision()->getRevisionNumber());
}
/**
 * @UniqueEntity(
 *      fields={"title"}
 * )
**/
最简单的解决方案似乎是在验证前提交后,但必须从实体中完成

我的问题是,在不覆盖Sonatarud控制器或其其他部分的情况下,如何(可以?)实现,甚至可能吗

这是可以做到的,但也存在一些问题:

我可以使用以下表单事件更改标题:

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(
...
);
当前的问题是,我正在获取“document”和“documentRevision”的ID,我至少需要它们的名称或\uu toString()表示形式。

另一个问题是,尽管我可以使用事件设置标题,但当它应该显示表单错误时,它会显示来自DB的错误,因为验证应该在
FormEvents::SUBMIT上完成-我不理解这一点。

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

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

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

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

关于实体数据,这可能会帮助您获取主题:

然后可以使用getter获取所需的数据,例如:

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

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

            // ...
    });
}
我还将此贴在您的问题上:

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

另外,需要注意的是,标记为@PrePersist、@PreUpdate等的函数必须是公共的,如果要这样使用它们,那么将它们标记为私有将导致原则失败

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

请参阅:(代码示例后的第一段)