我有一个实体Item
和实体File
当我用files
保存我的item
表单时,一切都可以,但稍后,当我尝试将新的File
添加到Item
时,所有相关文件都会从我的表中删除,我只得到新添加的项目。
删除发生在$form->handleRequest($request);
,我尝试在之前和之后转储数据,可以100%确认删除发生在那里。
然后用现有文件预填充我的$itemEntity
,但在$form
中的handleRequest
之后消失
我也使用add
方法而不是set
,并且在我的实体中有一个arrayCollection
我查看了探查器,可以看到正在发生的删除的原则SQL请求
对我来说,这似乎是一种非常奇怪的行为;我没有删除该项目,我甚至没有orphanRemoval
或cascade{delete}
。
最后,我不得不手动在数据库中重新创建旧文件的记录,但这似乎不合适,我确信我遗漏了一些东西。
百万美元的问题?
控制器
$itemEntity = $em->getRepository(Item::class)->findOneBy([
'uid' => $uid,
]);
// create form
$form = $this->createForm(NewItemType::class, $itemEntity);
// if I dump Item Entity here I can see my old files
$form->handleRequest($request);
// if I dump Item Entity here they are gone and replaced by the new ones
// .... later but never reached
$item->addFile($fileInstance);
项目实体:
/**
* @ORMOneToMany(targetEntity="AppEntityFile", mappedBy="item", cascade={"persist"})
*/
private $file;
public function __construct()
{
$this->file = new ArrayCollection();
}
文件实体:
/**
* @ORMId()
* @ORMGeneratedValue()
* @ORMColumn(type="integer")
*/
private $id;
/**
* @ORMColumn(type="string", length=255)
*/
private $path;
/**
* @ORMManyToOne(targetEntity="AppEntityItem", inversedBy="file")
* @ORMJoinColumn(nullable=false)
*/
private $item;
/**
* @ORMColumn(type="string", length=255)
*/
private $uid;
/**
* @ORMColumn(type="integer")
*/
private $type;
/**
* @ORMColumn(type="string", length=255, nullable=true)
*/
private $description;
/**
* @ORMColumn(type="integer", nullable=true)
*/
private $position;
/**
* @var boolean
* @ORMColumn(type="boolean", nullable=true)
*/
private $main;
/**
* @var UploadedFile|null
*/
protected $file;
public function getFile(): ?UploadedFile
{
return $this->file;
}
public function setFile(UploadedFile $file): void
{
$this->file = $file;
}
public function getId(): ?int
{
return $this->id;
}
public function getPath(): ?string
{
return $this->path;
}
public function setPath(string $path): self
{
$this->path = $path;
return $this;
}
public function getUid(): ?string
{
return $this->uid;
}
public function setUid(string $uid): self
{
$this->uid = $uid;
return $this;
}
public function getItem(): ?Item
{
return $this->item;
}
public function setBike(?Item $item): self
{
$this->item = $item;
return $this;
}
public function getType(): ?int
{
return $this->type;
}
public function setType(int $type): self
{
$this->type = $type;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(?string $description): self
{
$this->description = $description;
return $this;
}
public function getPosition(): ?int
{
return $this->position;
}
public function setPosition(?int $position): self
{
$this->position = $position;
return $this;
}
public function getMain(): ?bool
{
return $this->main;
}
public function setMain(?bool $main): self
{
$this->main = $main;
return $this;
}
表单集合类型
->add('item', CollectionType::class, array(
'label' => false,
'entry_type' => ItemFileType::class,
'error_bubbling' => false,
'entry_options' => [ 'required' => false, 'error_bubbling' => true ],
'allow_add' => true,
'allow_delete' => true
))
项目文件类型
->add('file', FileType::class, [
'label' => false,
'required' => false
])
->add('description')
->add('main', CheckboxType::class,[
'label' => 'Make this one the main picture',
'required' => false,
]);
这是ArrayCollection
的常见情况。首先,在Item
实体中有$file
变量
/**
* @ORMOneToMany(targetEntity="AppEntityFile", mappedBy="item", cascade={"persist"})
*/
private $file;
事实上,最好调用这个变量$files
,只要可以将几个或多个文件附加到一个项目即可。
您的代码中也应该有以下行
public function __construct() {
$this->files = new ArrayCollection();
}
这里的问题是,当您调用handleRequest
时,它会完全重写您的CCD_ 21属性。正如我所认为的,发生这种情况是因为您的Item
实体中只有set
方法,而您不应该有set方法,而是add
和remove
public function addFile(File $file)
{
if (!$this->files->contains($file)) {
$file->setItem($this);
$this->files->add($file);
}
return $this;
}
public function removeFile(File $file)
{
$this->files->removeElement($file);
return $this;
}
重点不是完全重写ArrayCollection
,而是扩展它。如果你从集合中删除某个项目,Doctrine会将其从数据库中删除。
仅供参考这也可能发生,因为$files
集合在提交表单之前没有预先填写现有集合