Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

In my symfony 2.7 application, I have the user entity based on FOSUserBundle. A user have to be connected in order to have access to an addAction() form.

My User entity is linked with another entity named parc. This is the code of my two entities.

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;
    }

Using the FOSUserBundle, in order to access to the connected user, in my twig view I make this: {{ app.user.username }}, which returms me the username of the current user.

Now, I would like to retrieve this value in my symfony form (for the field user) when I would like to add a parc. This my parcsType.php form:

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

This is my form in the twig view:

<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>

As you can see, I set the default value of my user field with {{ app.user.username }}, and it works, my user field returns me the current user. But when I submit the form, the user field and association (ManyToMany) between Parcs.php and Users.php are not persisted/flushed.

This is my controller code:

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() ));
         }
}

the submission works well, when I enter value for parc name the data is registered in my database, but not the users value and the ManyToMany association.

like image 499
french_dev Avatar asked Sep 22 '15 09:09

french_dev


2 Answers

You have to add the User object to the Parc object before creating the form. This way you don't even need the {'attr': {'value': app.user.username }} part.

Can you try this:

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() ));
         }
}

This way your form will be generated with the current user as default value in your users form field

like image 70
Snroki Avatar answered Nov 15 '22 06:11

Snroki


I found the solution,

As explained here, only the owning side is responsible for the connection management.

The problem was not with the method $parc->addUser($currentUser);, it's just that that entity Parcs was not the owner to manage this relation when would like to persist datas.

So I have inversed the entity owner properties. In Parcs.php the relation have to be like that:

/**
 * @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;

I have to remove the relation in Users.php in order to write this:

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

And this my controller for the 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() ));
         }
}

Thank you a lot by answering, noticed here that it was not the $parc->addUser($currentUser); who was making troubles, but the owner side of the relation.

like image 31
french_dev Avatar answered Nov 15 '22 04:11

french_dev