使用:Symfony 2.5SonataAdminBundle
当数据提交/保存到数据库时,我正试图通过使用关联实体(如(的两个字段来更改其中一个实体字段(标题(
文档修订版<-文档->CustomEntity[标题]=文档[标题]+文档修订[编号]
但CustomEntity的标题必须是唯一的——这是我试图解决的问题,并通过数据库约束和UniqueEntity验证进行管理(不完全是这样——稍后会详细介绍(。
现在的问题是,我更改了Doctrine preUpdate/Persist上的标题数据,有效地跳过了该字段的验证,因为它在验证时是空的。当用户放置错误的数据时,数据库层会为唯一约束抛出一个关于重复的错误。
/**
* @ORMPrePersist
* @ORMPreUpdate
*/
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"one_answers"documentRevision"的ID,并且我至少需要它们的名称或__toString((表示形式
另一个问题是,尽管我可以使用事件设置标题,但它显示DB中的错误,而它应该显示Form错误,因为验证应该在FormEvents::SUBMIT
上完成——我不理解这个
最后要注意的是,如果我尝试使用回调函数:
$builder->addEventListener(FormEvents::PRE_SUBMIT, array($this,'onPreSubmit'))
public function onPreSubmit() {
$entity = $this->getSubject();
$entity->setTitleFromDocumentName();
}
如果Entity试图从相关实体中获取字段,我将得到null标题和错误-在非对象上调用函数。
关于实体数据,这可能会帮助您获得主题: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
当我将唯一实体验证约束更改为我使用的从概念角度来看不完全有效的约束时,为了解决这个问题。
同样重要的是要注意,标记为@PrePersist、@PreUpdate等的函数必须是公共的,如果要这样使用,将其标记为私有将使条令失败。
请注意,设置为生命周期回调的方法需要是公共的,并且在使用这些注释时,必须在实体类上应用@HasLifecycleCallbacks标记注释。
请参阅:http://doctrine-orm.readthedocs.org/en/latest/reference/events.html#lifecycle-回调(代码示例后的第一段(。