【问题标题】:Symfony 2 - Change entity's field from Admin while keeping validation using SonataAdminBundleSymfony 2 - 从管理员更改实体的字段,同时使用 SonataAdminBundle 保持验证
【发布时间】:2014-08-05 09:09:31
【问题描述】:

使用: Symfony 2.5 SonataAdminBundle

当数据提交/保存到数据库时,我正在尝试更改其中一个实体字段(标题),方法是使用关联实体中的两个字段。

DocumentRevision CustomEntity [title] = Document[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 控制器或其其他部分,甚至可能吗?

可以,但是有问题:

我可以像这样使用表单事件更改标题:

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,我至少需要它们的名称或 __toString() 表示。

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

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

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

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

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

【问题讨论】:

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


    【解决方案1】:

    关于实体数据,这可能会帮助您了解主题: 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

    【讨论】:

      【解决方案2】:

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

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-03-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-19
        • 2021-07-14
        • 1970-01-01
        • 2014-09-30
        相关资源
        最近更新 更多