Symfony2多对多关系更新

时间:2015-06-29 08:34:08

标签: php symfony doctrine-orm many-to-many

我有多对多的关系,实际上是由第三个实体上的两个多对一组成。

Domain ← one-to-many → DomainTag ← many-to-one → Tag

我正在构建Rest API,我想通过特定路由将域添加到Tag。当标签没有关联时,一切正常。 但是当我尝试向标记添加新域时,如果标记已经作为一个(或多个)域,则会出错。 错误是

The form's view data is expected to be of type scalar, array or an instance of \ArrayAccess, but is an instance of class AppBundle\Entity\Domain. You can avoid this error by setting the "data_class" option to "AppBundle\Entity\Domain" or by adding a view transformer that transforms an instance of class AppBundle\Entity\Domain to scalar, array or an instance of \ArrayAccess.

以下是三个实体: 标签

class Tag
{
    …

    /**
    * @ORM\OneToMany(targetEntity="DomainTag", mappedBy="tag", cascade={"persist", "remove"})
    */
    private $domainTags;

    …
}

DomainTag

class DomainTag
{
    …

    /**
    * @var Tag
    *
    * @ORM\ManyToOne(targetEntity="Tag", inversedBy="domainTags")
    * @ORM\JoinColumns({
    *   @ORM\JoinColumn(name="tag_id", referencedColumnName="id")
    * })
    */
    private $tag;        

    /**
    * @var Domain
    *
    * @ORM\ManyToOne(targetEntity="Domain", inversedBy="domainTags")
    * @ORM\JoinColumns({
    *   @ORM\JoinColumn(name="domain_id", referencedColumnName="id")
    * })
    */
    private $domain;

    …
}

class Domain
{
    …

    /**
    * @ORM\OneToMany(targetEntity="DomainTag", mappedBy="domain", cascade={"persist", "remove"})
    */
    private $domainTags;

    …
}

这是表格

class AddDomainTagFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('domainTags', 'collection', array(
                'type' => new DomainTagFormType(),
                'allow_add' => true,
            ))
        ;
    }

    // BC for SF < 2.7
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Tag',
            'csrf_protection' => false,
        ));
    }

    public function getName()
    {
        return 'api_set_domaintag';
    }
}

DomainTagFormType

class DomainTagFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
        ->add('weight')
        ->add('domain', 'entity', array(
                'class' => 'AppBundle:Domain',
                'property' => 'id',
                'multiple' => false,
                'expanded' => true
            ))
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\DomainTag',
            'csrf_protection' => false,
        ));
    }

    // BC for SF < 2.7
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $this->configureOptions($resolver);
    }

    public function getName()
    {
        return 'api_domaintag';
    }
}

最后,控制器

    /**
     * @Rest\Put("/{id}/domains", requirements={"id" = "\d+"})
     * @Security("has_role('ROLE_SUPER_ADMIN')")
     * @Rest\View
     */
    public function setDomainAction(Request $request, $id)
    {
        $tagManager = $this->get('app.manager.tag');
        $domainManager = $this->get('app.manager.domain');

        $tag = $tagManager->find($id);

        if (!$tag) {
            return new Response('Tag not found', 404);
        }

        $form = $this->createForm(new AddDomainTagFormType(), $tag, array('method' => 'PUT'));

        $form->handleRequest($request);

        if ($form->isValid()) {
            foreach ($tag->getDomainTags() as $dt) {
                $dt->setTag($tag);
                $tagManager->persist($dt);
            }
            $tagManager->flush($tag);

            return new Response('', 204);
        } else {
            return $this->view($form, 400);
        }
    }

我是否必须从标记中删除所有DomainTag并重新创建所有关联?或者有没有办法只添加/删除DomainTags?

谢谢

0 个答案:

没有答案