2

I'm new of Symfony and php, and I'm trying to understand, without outcome, the array collection.

Now I have two entity, Mission and User, in relation ManytoMany. I have a form to create new Missions and a form to create new User.

Now I have to create a "modifyMissionAction" that allows me to set the Users for that missions, but I didn't understand how to do it. I read the documentation here but it doesn't help. How could I do?

Thank you

This is my User Entity is:

 abstract class User extends BaseUser
 {

      /**
      * @var \Doctrine\Common\Collections\ArrayCollection
      * 
      * @ORM\ManyToMany(targetEntity="Acme\ManagementBundle\Entity\Mission", inversedBy="users", orphanRemoval=true)
      * @ORM\JoinTable(name="user_mission")
      */
     private $missions;    
     /**
      * Add missions
      *
      * @param \Acme\ManagementBundle\Entity\Mission $missions
      * @return User
      */
     public function addMission(\Acme\ManagementBundle\Entity\Mission $missions)
     {
         $this->missions[] = $missions;

         return $this;
     }
//...

And my Mission Entity:

<?php

namespace Acme\ManagementBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;

/**
 * @ORM\Entity
 */
class Mission {
    /** 
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     * @var integer
     */
    protected $id;
        /** 
     * @ORM\Column(type="string", length=60)
     * @var String
     */
    protected $name;
    /** 
     * @ORM\Column(type="string", length=600)
     * @var String
     */
    protected $description;
    /**
     * @var \Doctrine\Common\Collections\ArrayCollection
     *
     * @ORM\ManyToMany(targetEntity="Acme\ManagementBundle\Entity\User", mappedBy="missions", cascade={"all"}, orphanRemoval=true)
     */
    private $users;

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

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set name
     *
     * @param string $name
     * @return Mission
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string 
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Set description
     *
     * @param string $description
     * @return Mission
     */
    public function setDescription($description)
    {
        $this->description = $description;

        return $this;
    }

    /**
     * Get description
     *
     * @return string 
     */
    public function getDescription()
    {
        return $this->description;
    }

    /**
     * Add users
     *
     * @param \Acme\ManagementBundle\Entity\User $users
     * @return Mission
     */
    public function addUser(\Acme\ManagementBundle\Entity\User $users)
    {
        $this->users[] = $users;

        return $this;
    }

    /**
     * Remove users
     *
     * @param \Acme\ManagementBundle\Entity\User $users
     */
    public function removeUser(\Acme\ManagementBundle\Entity\User $users)
    {
        $this->users->removeElement($users);
    }

    /**
     * Get users
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getUsers()
    {
        return $this->users;
    }
    public function __toString()
    {
        return $this->name;
    }
}
Gianni Alessandro
  • 860
  • 6
  • 11
  • 28

1 Answers1

2

first of all don't forget to add __constructor for both of classes and init ArrayCollection:

//src/WebHQ/NewBundle/Entity/Mission.php
//...
public function __construct()
{
    $this->users = new ArrayCollection();
}
//...

I assume that you want to add controller action witch allows you to relate user object or objects to mission object. Please read embbed forms part of Symfony book

Then create your Action. Most important is to add form element, with is embedded form of users entity:

// src/WebHQ/NewBundle/Controller/MissionController.php
//...
public function newAction(Request $request)
{
    $object = new \WebHQ\NewBundle\Entity\Mission();

    $form = $this->createFormBuilder($object)
            ->add('name', 'text')
            //...
            // Users objects embed form
            ->add('users', 'user')
            //...
            ->add('save', 'submit')
            ->getForm();

    if ($request->isMethod('POST')) {
        $form->bind($request);

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

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

    return $this->render('WebHQNewBundle:Mission:new.html.twig', array(
        'form'      => $form->createView(),
        //...
    ));
}

public function editAction($id, Request $request)
{
    $object = $this->getDoctrine()
            ->getRepository('WebHQNewBundle:Mission')
            ->find($id);

    $form = $this->createFormBuilder($object)
            ->add('name', 'text')
            //...
            ->add('users', 'user')
            //...
            ->add('save', 'submit')
            ->add('delete', 'submit')
            ->getForm();

    if ($request->isMethod('POST')) {
        $form->bind($request);

        if ($form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $form->get('save')->isClicked() ? $em->persist($object) : $em->remove($object);
            $em->flush();

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

    return $this->render('WebHQNewBundle:Mission:edit.html.twig', array(
        'form'      => $form->createView(),
        //...
    ));
}
//...

Check your routing. You should have route for edit action with {id} param. If name of param not fits you change it in route and in function definition:

// src/WebHQ/NewBundle/Resources/config/route.yml
//...
web_hq_new_mission_new:
    pattern: /mission/new
    defaults: { _controller: WebHQNewBundle:Mission:new }

web_hq_new_mission_edit:
    pattern: /mission/{id}/edit
    defaults: { _controller: WebHQNewBundle:Mission:edit }
//...

Then define Form Type for User objects:

// src/WebHQ/NewBundle/Form/Type/UserType.php
namespace WebHQ\NewBundle\Form\Type;

use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;


class UserType extends AbstractType
{
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'class' => 'WebHQNewBundle:User',
            'property' => 'name',
            'empty_value' => 'Choose',
            'required' => true,
            'multiple' => true,
            'query_builder' => function (Options $options) {
                return function(EntityRepository $er) use ($options) {
                    return $er->createQueryBuilder('c')
                        ->orderBy('c.name', 'ASC');
                };
            },
        ));
    }

    public function getParent()
    {
        return 'entity';
    }

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

And register a type in service.yml:

# src/WebHQ/NewBundle/Resources/config/services.yml
#...
services:
    web_hq_new.form.type.user:
        class: WebHQ\NewBundle\Form\Type\UserType
        tags:
            - { name: form.type, alias: user }
#...

Good Luck!

WebHQ
  • 711
  • 8
  • 21
  • Thank you for the answer. Actually I still have some problem, when I call the page edit/mission the following alarm appears: Neither the property "user" nor one of the methods "getUser()", "isUser()", "hasUser()", "__get()" exist and have public access in class "Acme\ManagementBundle\Entity\Mission". I edited the question and showed my whole Mission entity. – Gianni Alessandro Jan 29 '14 at 15:42
  • Im sorry, I have made a typo. In controller, editAction, change line `->add('user', 'user')` to `->add('users', 'user')`. "users" is an attribute name, "user" is a form type. This should fix for error. – WebHQ Jan 29 '14 at 16:21
  • In addition, you can change FormType parameters, when adding it to form in controllers action. E.g if you don't want to _require_ users to have related object, field not required, you can call it like this: `->add('users', 'user', array('require' => false))` – WebHQ Jan 29 '14 at 16:30
  • Great, it works. Actually it creates a new mission with the users associated; now I'm trying to create an editAction that allows to associate existing mission with existing user, but I'm reading the documentation and I think that I can do it. If I have problem I will comment here. Thank you! – Gianni Alessandro Jan 29 '14 at 17:04
  • Ok, I have added both actions for you. The difference is that editAction has `$id` param passed from routing. Please check your routing file if there is `{id}` param passed. I have include an example of routing. – WebHQ Jan 29 '14 at 18:25
  • And another thing. This edit action has also delete button ;) So if you click save, `$em->persist($object)` will be executed and if you click delete `$em->remove($object)` will be launched. Full line looks like this: `$form->get('save')->isClicked() ? $em->persist($object) : $em->remove($object);` – WebHQ Jan 29 '14 at 18:29
  • Great again. I have done in a different way, but this one is better and I also learned something new. Really thank you! – Gianni Alessandro Jan 29 '14 at 18:50
  • Can I ask you one more [thing](http://stackoverflow.com/questions/21446285/arraycollection-retrive-collection-in-a-form?noredirect=1#comment32361973_21446285)? I opened a new post for it. (I will delete this comment because it is not directly related to the question) – Gianni Alessandro Jan 30 '14 at 04:34
  • @Jivan was first to answer :) And I think he is right. – WebHQ Jan 30 '14 at 12:17