在ManyToMany双向上的EntityForm,用于关系的两个方面

时间:2016-04-27 09:20:09

标签: symfony

我有2个实体:User和Strain具有ManyToMany双向关系,关系的所有者是User。

我想做一个用于编辑权限的表单(用户拥有一些Strains),当我为User做一个表单,我可以选择一些我想要的Strains时,它工作正常(我在Strain上使用EntityType)。但是......有时,我想要通过关系的另一面编辑权利:应变。即编辑Strain并选择我想要的用户。但它不起作用......

我给你我的实体User和Strain以及两个FormType和我的Uglys解决方案......

user.php的

/**
 * The authorized strains for this user.
 * 
 * @var Strain|ArrayCollection
 *
 * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Strain", inversedBy="authorizedUsers")
 */
private $authorizedStrains;

/**
 * User constructor.
 */
public function __construct()
{
    $this->authorizedStrains = new ArrayCollection();
}

/**
 * Add an authorized strain.
 *
 * @param Strain $strain
 * 
 * @return $this
 */
public function addAuthorizedStrain(Strain $strain)
{
    $this->authorizedStrains[] = $strain;
    $strain->addAuthorizedUser($this);

    return $this;
}

/**
 * Remove an authorized strain.
 *
 * @param Strain $strain
 */
public function removeAuthorizedStrain(Strain $strain)
{
    $this->authorizedStrains->removeElement($strain);
    $strain->removeAuthorizedUser($this);
}

/**
 * Get authorized strains.
 *
 * @return Strain|ArrayCollection
 */
public function getAuthorizedStrains()
{
    return $this->authorizedStrains;
}

Strain.php

/**
 * The authorized user.
 * For private strains only.
 * 
 * @var User|ArrayCollection
 * 
 * @ORM\ManyToMany(targetEntity="AppBundle\Entity\User", mappedBy="authorizedStrains")
 */
private $authorizedUsers;

/**
 * Strain constructor.
 */
public function __construct()
{

/**
 * Add authorized user.
 *
 * @param User $user
 *
 * @return $this
 */
public function addAuthorizedUser(User $user)
{
    $this->authorizedUsers[] = $user;

    return $this;
}

/**
 * Remove authorized user.
 *
 * @param User $user
 */
public function removeAuthorizedUser(User $user)
{
    $this->authorizedUsers->removeElement($user);
}

/**
 * Get authorized users.
 *
 * @return User|ArrayCollection
 */
public function getAuthorizedUsers()
{
    return $this->authorizedUsers;
}

UserRightsType.php

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('authorizedStrains', EntityType::class, array(
            'class' => 'AppBundle\Entity\Strain',
            'choice_label' => 'name',
            'expanded' => true,
            'multiple' => true,
            'required' => false,
        ))
    ;
}

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

StrainRightsType

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('authorizedUsers', EntityType::class, array(
            'class' => 'AppBundle\Entity\User',
            'query_builder' => function(UserRepository $ur) {
              return $ur->createQueryBuilder('u')
                  ->orderBy('u.username', 'ASC');
            },
            'choice_label' => function ($user) {
                return $user->getUsername().' ('.$user->getFirstName().' '.$user->getLastName().')';
            },
            'expanded' => true,
            'multiple' => true,
            'required' => false,
        ))
    ;
}

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

StrainController.php 丑陋的解决方案

public function userRightsAction(Request $request, Strain $strain)
{
    $form = $this->createForm(StrainRightsType::class, $strain);
    $form->add('save', SubmitType::class, [
        'label' => 'Valid the rights',
    ]);

    foreach($strain->getAuthorizedUsers() as $authorizedUser) {
        $authorizedUser->removeAuthorizedStrain($strain);
    }

    $form->handleRequest($request);

    if ($form->isValid()) {
        $em = $this->getDoctrine()->getManager();

        foreach($strain->getAuthorizedUsers() as $authorizedUser)
        {
            $authorizedUser->addAuthorizedStrain($strain);
            $em->persist($authorizedUser);
        }

        $em->flush();

        $request->getSession()->getFlashBag()->add('success', 'The user\'s rights for the strain '.$strain->getName().' were successfully edited.');

        return $this->redirectToRoute('strain_list');
    }

    return $this->render('strain/userRights.html.twig', [
        'strain' => $strain,
        'form' => $form->createView(),
    ]);
}

正如你所看到的,我做了2个foreach:第一个删除了Strain的所有权利,第二个删除了权利。

我认为Symfony已经预料到了这个问题,但我不知道该怎么办,而且我在文档中找不到任何内容......

提前感谢您的帮助, 谢泼德

1 个答案:

答案 0 :(得分:0)

最后,我找到了。

在反面(Strain.php):

public function addAuthorizedUser(User $user)
{
    $user->addAuthorizedStrain($this);
    $this->authorizedUsers[] = $user;

    return $this;
}

public function removeAuthorizedUser(User $user)
{
    $user->removeAuthorizedStrain($this);
    $this->authorizedUsers->removeElement($user);
}

并且,在所有者方面(User.php)

public function addAuthorizedStrain(Strain $strain)
{
    if (!$this->authorizedStrains->contains($strain)) {
        $this->authorizedStrains[] = $strain;
    }

    return $this;
}

public function removeAuthorizedStrain(Strain $strain)
{
    if ($this->authorizedStrains->contains($strain)) {
        $this->authorizedStrains->removeElement($strain);
    }
}

在FormType(反面)(StrainRightsType))中,添加'by_reference'=>假

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('authorizedUsers', EntityType::class, array(
            'class' => 'AppBundle\Entity\User',
            'query_builder' => function(UserRepository $ur) {
              return $ur->createQueryBuilder('u')
                  ->orderBy('u.username', 'ASC');
            },
            'choice_label' => function ($user) {
                return $user->getUsername().' ('.$user->getFirstName().' '.$user->getLastName().')';
            },
            'by_reference' => false,
            'expanded' => true,
            'multiple' => true,
            'required' => false,
        ))
    ;
}