Symfony2.8.10 と Doctrine を使って、コレクションを永続化することについて質問があります。
以下の2つのクラス 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,
            ]);
    }

上記コードはフォームタイプの一部です。

 
 いくつかの 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);
    }

 変更後は、削除した項目がデータベースから正しく削除されました。
 しかし、これは汚いと考えます。
 この問題を回避する正しい方法をお教えください。
 あなたの助けを大いに評価します。