如何根据实体之间的 ManyToMany 关系将默认值设置为已连接用户之后的 symfony 表单字段(用户字段)

how to set default value to a symfony form field (User field) following the connected user, following the ManyToMany relation between entities

在我的 symfony 2.7 应用程序中,我有基于 FOSUserBundle 的用户实体。必须连接用户才能访问 addAction() 表单。

我的用户实体与另一个名为 parc 的实体链接。这是我两个实体的代码。

Users.php

class Users extends BaseUser
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    public function __construct()
    {
        parent::__construct();
        $this->parcs = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
     * @var \Doctrine\Common\Collections\Collection
     *
     * @ORM\ManyToMany(targetEntity="Parcs", inversedBy="users")
     * @ORM\JoinTable(name="users_parcs",
     *   joinColumns={
     *     @ORM\JoinColumn(name="user_id", referencedColumnName="id")
     *   },
     *   inverseJoinColumns={
     *     @ORM\JoinColumn(name="parc_id", referencedColumnName="id")
     *   }
     * )
     */
    private $parcs;

    /**
     * Get parcs
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getParcs()
    {
        return $this->parcs;
    }

    /**
     * Set parcs
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function setParcs($parcs)
    {
        return $this->parcs;
    }

Parcs.php

class Parcs
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var \Doctrine\Common\Collections\Collection
     *
     * @ORM\ManyToMany(targetEntity="Users", mappedBy="parcs")
     */
    private $users;

    public function __construct()
    {
      $this->users = new \Doctrine\Common\Collections\ArrayCollection();
    }

//rest of my entity attributes, object, properties etc

// getters and setters

    /**
     * Get users
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getUsers()
    {
        return $this->users;
    }

    /**
     * Set users
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function setUsers($users)
    {
        return $this->users;
    }

   /**
    * Add user
     *
     * @param \MySpace\MyBundle\Entity\Users $user
     *
     * @return Parcs
     */
    public function addUser(\MySpace\MyBundle\Entity\Users $user)
    {
        $this->users[] = $user;

        return $this;
    }

使用 FOSUserBundle,为了访问已连接的用户,在我的 twig 视图中我做了这个:{{ app.user.username }},它返回我当前用户的用户名。

现在,当我想添加一个 parc 时,我想在我的 symfony 表单(对于现场用户)中检索这个值。 这是我的 parcsType.php 表格:

public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('parcName')
            ->add('users')
        ;
    }

这是我在树枝视图中的表单:

<form action="{{ path('addParcs_process') }}" method="POST" {{ form_enctype(form) }}>
  <div>
    {{ form_label(form.parcName, "Enter the parc name: ", {'label_attr': {'class': 'control-label'}}) }}
    {{ form_errors(form.parcName) }}
    {{ form_widget(form.parcName) }}
  </div>
  <div>
    {{ form_label(form.users, "Vous ajoutez ce parc en tant que: ", {'label_attr': {'class': 'control-label'}}) }}
    {{ form_errors(form.users) }}
    {{ form_widget(form.users, {'attr': {'value': app.user.username }}) }}
  </div>
  <input type="submit" value="Ajouter" class="btn btn-success"/>
</form>

如您所见,我将我的用户字段的默认值设置为 {{ app.user.username }},它起作用了,我的用户字段 returns 我是当前用户。但是当我提交表单时,Parcs.phpUsers.php之间的用户字段和关联(ManyToMany)不是persisted/flushed。

这是我的控制器代码:

public function addParcsAction() {

    if (!$this->get('security.context')->isGranted('ROLE_EDIT')) {
      throw new HttpException("403");
    }

    $em=$this->getDoctrine()->getManager();
    $parc = new Parcs;

    $form=$this->createForm(new ParcsType(), $parc);
    $form->add('user');
    $request = $this->getRequest();

    if ($request->isMethod('POST') | ($form->isValid())) {

            $form->bind($request);

            $currentUser=$this->container->get('security.context')->getToken()->getUser();
            $parc->setUsers($currentUser);

            $parc = $form->getData();
            $em->persist($parc);
            $em->flush();

            return $this->redirect($this->generateUrl('indexParc'));
        }

    else {
            return $this->render('MySpaceMyBundle:Parcs:addParcs.html.twig', array('form' => $form->createView() ));
         }
}

提交效果很好,当我输入 parc 名称的值时,数据已在我的数据库中注册,但用户值和 ManyToMany 关联没有。

您必须在创建表单之前将 User 对象添加到 Parc 对象。这样你甚至不需要 {'attr': {'value': app.user.username }} 部分。

你能试试这个吗:

public function addParcsAction() {

    if (!$this->get('security.context')->isGranted('ROLE_EDIT')) {
      throw new HttpException("403");
    }

    $em=$this->getDoctrine()->getManager();
    $parc = new Parcs;
    $currentUser = $this->container->get('security.context')->getToken()->getUser();
    $parc->addUser($currentUser);

    $form = $this->createForm(new ParcsType(), $parc);
    $request = $this->getRequest();

    if ($request->isMethod('POST') | ($form->isValid())) {

            $form->bind($request);

            $parc = $form->getData();
            $em->persist($parc);
            $em->flush();

            return $this->redirect($this->generateUrl('indexParc'));
        }

    else {
            return $this->render('MySpaceMyBundle:Parcs:addParcs.html.twig', array('form' => $form->createView() ));
         }
}

这样您的表单将以当前用户作为默认值生成在您的 users 表单字段中

我找到了解决方案,

here所述,只有拥有方负责连接管理。

问题不在于方法 $parc->addUser($currentUser);,只是实体 Parcs 不是在想要持久化数据时管理此关系的所有者。

所以我已经反转了实体所有者的属性。在 Parcs.php 中,关系必须是这样的:

/**
 * @var \Doctrine\Common\Collections\Collection
 *
 * @ORM\ManyToMany(targetEntity="Users", inversedBy="parcs")
 * @ORM\JoinTable(name="parcs_users",
 *   joinColumns={
 *     @ORM\JoinColumn(name="parc_id", referencedColumnName="id")
 *   },
 *   inverseJoinColumns={
 *     @ORM\JoinColumn(name="user_id", referencedColumnName="id")
 *   }
 * )
 */
private $users;

我必须删除 Users.php 中的关系才能这样写:

/**
 * @var \Doctrine\Common\Collections\Collection
 *
 * @ORM\ManyToMany(targetEntity="Parcs", mappedBy="users")
 */
private $parcs;

这是我的 addAction() 控制器:

public function addParcsAction() {

    if (!$this->get('security.context')->isGranted('ROLE_EDIT')) {
      throw new HttpException("403");
    }

    $em=$this->getDoctrine()->getManager();
    $parc = new Parcs;
    $currentUser = $this->container->get('security.context')->getToken()->getUser();
    $parc->addUser($currentUser);

    $form = $this->createForm(new ParcsType(), $parc);
    $request = $this->getRequest();

    if ($request->isMethod('POST') | ($form->isValid())) {

            $form->bind($request);

            $parc = $form->getData();
            $em->persist($parc);
            $em->flush();

            return $this->redirect($this->generateUrl('indexParc'));
        }

    else {
            return $this->render('MySpaceMyBundle:Parcs:addParcs.html.twig', array('form' => $form->createView() ));
         }
}

非常感谢您的回答,注意到这里不是 $parc->addUser($currentUser);谁惹的祸,可是关系的主人方