Reputation: 1635
First of all: the error I'm getting is: Entities passed to the choice field must be managed
I have these entities: - user (belongs to one or many teams) - team (has one or 2 users) - challenge (has 2 teams)
I'd like to build a ChallengeType form where a user can fill in the two users for the two teams and create the challenge. I think I need an embedded form here.
I've made a TeamType Form class: (I would expect to get a select box from this, where all users are listed)
<?php
namespace Tennisconnect\DashboardBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
class TeamType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('players', 'entity', array(
'class' => 'TennisconnectUserBundle:User',
'multiple' => true
));
}
public function getName()
{
return 'team';
}
public function getDefaultOptions(array $options)
{
return array('data_class' => 'Tennisconnect\DashboardBundle\Entity\Team');
}
}
This is the ChallengeType form class:
<?php
namespace Tennisconnect\DashboardBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
class ChallengeType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('teams', 'collection', array('type' => new TeamType()));
}
public function getName()
{
return 'challenge';
}
public function getDefaultOptions(array $options)
{
return array('data_class' => 'Tennisconnect\DashboardBundle\Entity\Challenge');
}
}
Challenge entity:
namespace Tennisconnect\DashboardBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Tennisconnect\DashboardBundle\Entity\Team;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @ORM\Entity
* @ORM\Table(name="challenge")
*/
class Challenge
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\ManyToMany(targetEntity="Team", mappedBy="teams")
*/
protected $teams;
public function __construct()
{
$this->teams = new ArrayCollection();
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Add teams
*
* @param Tennisconnect\DashboardBundle\Entity\Team $teams
*/
public function addTeam(Team $teams)
{
$this->teams[] = $teams;
}
/**
* Get teams
*
* @return Doctrine\Common\Collections\Collection
*/
public function getTeams()
{
return $this->teams;
}
}
Team entity:
namespace Tennisconnect\DashboardBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
use Tennisconnect\UserBundle\Entity\User;
use Tennisconnect\DashboardBundle\Entity\Challenge;
use Tennisconnect\DashboardBundle\Entity\Match;
/**
* @ORM\Entity
* @ORM\Table(name="team")
*/
class Team
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\ManyToMany(targetEntity="Tennisconnect\UserBundle\Entity\User", mappedBy="teams")
*/
protected $players;
/**
* @ORM\ManyToMany(targetEntity="challenge", inversedBy="teams", cascade= {"persist"})
*/
protected $challenges;
/**
* @ORM\ManyToMany(targetEntity="Match", inversedBy="teams")
*/
protected $matches;
public function __construct()
{
$this->players = new ArrayCollection();
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Add players
*
* @param Tennisconnect\UserBundle\Entity\User $players
*/
public function addUser(User $players)
{
$this->players[] = $players;
}
/**
* Get players
*
* @return Doctrine\Common\Collections\Collection
*/
public function getPlayers()
{
return $this->players;
}
/**
* Add matches
*
* @param Tennisconnect\DashboardBundle\Entity\Match $matches
*/
public function addMatch(Match $matches)
{
$this->matches[] = $matches;
}
/**
* Get matches
*
* @return Doctrine\Common\Collections\Collection
*/
public function getMatches()
{
return $this->matches;
}
/**
* Add challenges
*
* @param Tennisconnect\DashboardBundle\Entity\challenge $challenges
*/
public function addchallenge(challenge $challenges)
{
$this->challenges[] = $challenges;
}
/**
* Get challenges
*
* @return Doctrine\Common\Collections\Collection
*/
public function getChallenges()
{
return $this->challenges;
}
}
Challenge controller:
class ChallengeController extends Controller
{
public function newAction()
{
$challenge = new Challenge();
$form = $this->createForm(new ChallengeType(), $challenge);
return $this->render('TennisconnectDashboardBundle:Challenge:new.html.twig', array('form' => $form->createView()));
}
}
Upvotes: 6
Views: 9447
Reputation: 3012
If you have the error Entities passed to the choice field must be managed. Maybe persist them in the entity manager?
with a ManyToMany
relationship between 2 entities, when using a form type, it may come from your entity constructor :
If your form is "TeamType", try to remove the ArrayCollection initialization of your "Team" entity.
Your Team class become :
namespace Tennisconnect\DashboardBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
use Tennisconnect\UserBundle\Entity\User;
use Tennisconnect\DashboardBundle\Entity\Challenge;
use Tennisconnect\DashboardBundle\Entity\Match;
/**
* @ORM\Entity
* @ORM\Table(name="team")
*/
class Team
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\ManyToMany(targetEntity="Tennisconnect\UserBundle\Entity\User", mappedBy="teams")
*/
protected $players;
/**
* @ORM\ManyToMany(targetEntity="challenge", inversedBy="teams", cascade= {"persist"})
*/
protected $challenges;
/**
* @ORM\ManyToMany(targetEntity="Match", inversedBy="teams")
*/
protected $matches;
public function __construct()
{
// REMOVE $this->players = new ArrayCollection();
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Add players
*
* @param Tennisconnect\UserBundle\Entity\User $players
*/
public function addUser(User $players)
{
$this->players[] = $players;
}
/**
* Get players
*
* @return Doctrine\Common\Collections\Collection
*/
public function getPlayers()
{
return $this->players;
}
/**
* Add matches
*
* @param Tennisconnect\DashboardBundle\Entity\Match $matches
*/
public function addMatch(Match $matches)
{
$this->matches[] = $matches;
}
/**
* Get matches
*
* @return Doctrine\Common\Collections\Collection
*/
public function getMatches()
{
return $this->matches;
}
/**
* Add challenges
*
* @param Tennisconnect\DashboardBundle\Entity\challenge $challenges
*/
public function addchallenge(challenge $challenges)
{
$this->challenges[] = $challenges;
}
/**
* Get challenges
*
* @return Doctrine\Common\Collections\Collection
*/
public function getChallenges()
{
return $this->challenges;
}
}
Upvotes: 3
Reputation: 1635
The problem is solved. I had to add the "allow_add" option to my collection in the ChallengeType class.
The challenge controller class needed some editing too. I added 2 teams to the Challenge object before passing it through to the form.
Upvotes: 1
Reputation: 17678
You've created forms that are displaying a ManyToMany
collection; set the multiple
option in your formbuilder for those widgets to true
(it defaults false, which fundamentally conflicts with a ToMany
relationship).
Upvotes: 19