我对Symfony2.8.10和Doctrine中的集合持久性有疑问。 我写了以下实体类,Article和ArticleAttribute。
/**
* Article
*
* @ORM\Table(name="article")
* @ORM\Entity(repositoryClass="AppBundle\Repository\ArticleRepository")
* @ORM\HasLifecycleCallbacks
* */
class Article
{
/** @ORM\Id @ORM\Column(type="integer") */
private $id;
/** @ORM\Column(type="string") */
private $title;
/**
* @var ArticleAttribute[]
* @ORM\OneToMany(targetEntity="ArticleAttribute", mappedBy="article", cascade={"ALL"})
*/
private $attributes;
/**
* Constructor
*/
public function __construct()
{
$this->attributes = new ArrayCollection();
}
/**
* Get attributes
*
* @return ArticleAttribute[]
*/
public function getAttributes()
{
return $this->attributes;
}
/**
* @param $item ArticleAttribute
*/
public function addAttribute($item)
{
$this->attributes[$item->getAttribute()] = $item;
$item->setArticle($this);
}
/**
* Remove attributes
*
* @param ArticleAttribute $attribute
*/
public function removeAttribute(ArticleAttribute $attribute)
{
$this->attributes->removeElement($attribute);
}
...
/**
* @ORM\Table(name="article_attribute")
* @ORM\Entity
*/
class ArticleAttribute
{
/**
* @var Article
* @ORM\Id
* @ORM\ManyToOne(targetEntity="Article", inversedBy="attributes")
* @ORM\JoinColumn(name="article_id", referencedColumnName="id")
*/
private $article;
/**
* @ORM\Id
* @ORM\Column(type="string")
*/
private $attribute;
/**
* Get article
*
* @return Article
*/
public function getArticle()
{
return $this->article;
}
/**
* Set article
*
* @param Article $article
* @return ArticleAttribute
*/
public function setArticle(Article $article)
{
$this->article = $article;
return $this;
}
....
绑定形成这些类。
class ArticleType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('id')
->add('title')
->add('attributes', CollectionType::class, [
'entry_type' => ArticleAttributeType::class,
'allow_add' => true,
'allow_delete' => true,
]);
}
上面的代码是FormType的一部分。
在页面上删除多个ArticleAttributes。 提交表格。 调用handleRequest和$ em-> flush(); 但删除的项目仍保留在数据库中。
我找到了解决此问题的方法。 我在FormResizeListener类中修改了onSubmit方法。
public function onSubmit(FormEvent $event)
{
/** @var FormBuilder $form */
$form = $event->getForm();
/** @var PersistentCollection $data */
$data = $event->getData();
// At this point, $data is an array or an array-like object that already contains the
// new entries, which were added by the data mapper. The data mapper ignores existing
// entries, so we need to manually unset removed entries in the collection.
if (null === $data) {
$data = [];
}
if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) {
throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)');
}
if ($this->deleteEmpty) {
$previousData = $event->getForm()->getData();
foreach ($form as $name => $child) {
$isNew = !isset($previousData[$name]);
// $isNew can only be true if allowAdd is true, so we don't
// need to check allowAdd again
if ($child->isEmpty() && ($isNew || $this->allowDelete)) {
unset($data[$name]);
$form->remove($name);
}
}
}
// The data mapper only adds, but does not remove items, so do this
// here
if ($this->allowDelete) {
$arr = (array)$data; //added
/** @var EntityManager $em */ //added
$em = @$arr["\0Doctrine\\ORM\\PersistentCollection\0em"]; //added
$toDelete = [];
foreach ($data as $name => $child) {
if (!$form->has($name)) {
$toDelete[] = $name;
}
}
foreach ($toDelete as $name) {
if ($em) $em->remove($data[$name]); //added
unset($data[$name]);
}
}
$event->setData($data);
}
通过调用$ em->删除,将已删除项目的删除注册到工作单元。
修改后。已删除的项目正确地从数据库中删除 但我觉得这很讨厌。 请告诉我正确的方法来避免这个问题。 我很感激你的帮助。
答案 0 :(得分:2)
尝试修改与Article
添加ArticleAttributes
选项
orphanRemoval
关系
/**
* @var ArticleAttribute[]
* @ORM\OneToMany(targetEntity="ArticleAttribute", mappedBy="article", cascade={"ALL"}, orphanRemoval=true)
*/
private $attributes;
我还建议阅读this article