EDIT is an overridden question and included additional custom code
In my Symfony2 project, I have an entity ( Configurations ) that includes OneToMany relationships with another object ( Configurations Features). I am trying to create a form that allows the user to change values โโin the Configurations entity, as well as select the values โโthat should be stored in the ConfigurationsFeatures object. There are two scenarios in which the form is used:
1) Create a new configuration โ visualize an empty form with fields for the values โโin the Configuration and a collection of flags for potential values โโin the ConfigurationsFeatures; the source of potential values โโis actually the third object, CoreCodes . After checking the Configurations values, the forms are saved in the Configurations object, and the selected checkboxes are saved in ConfigurationsFeatures.
2) Update the existing configuration โ visualize the form with the existing configuration values โโdisplayed in the fields and create a collection of checkboxes for all possible ConfigurationsFeatures, but existing values โโare already selected.
I created a form type and controller action for scenario # 1, tested it, and everything works. However, I cannot decide that "pre-existing values โโare already selected" in the form's check box. I understand that as I am currently setting up my controller, I basically compare apples to oranges because $ entity-> getFeatures () returns an ArrayCollection of a ConfigurationsFeatures object and has nothing to match in the form because the form uses a collection of CoreCodes objects.
So how do I bridge this gap?
Entity \ Configurations (saves individual configurations)
use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; /** * Lynux\AssetBundle\Entity\Core\Configurations * ... ORM declarations ... */ class Configurations { // ... plain old properties, nothing fancy here... /** * @ORM\OneToMany(targetEntity="Lynux\AssetBundle\Entity\Core\ConfigurationsFeatures", mappedBy="configurationFk") */ private $features; public function __construct() { $this->features = new ArrayCollection(); } // getters and setters /** * Set features */ public function setFeatures(ArrayCollection $features) { $this->features = $features; } /** * Get features */ public function getFeatures() { return $this->features; } }
Entity \ ConfigurationsFeatures (saves selected functions for each configuration)
use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; class ConfigurationsFeatures { private $featureFk; private $configurationFk; public function setFeatureFk(\Lynux\AssetBundle\Entity\Core\Codes $featureFk = null) { $this->featureFk = $featureFk; return $this; } public function getFeatureFk() { return $this->featureFk; } public function setConfigurationFk(\Lynux\AssetBundle\Entity\Core\Configurations $configurationFk = null) { $this->configurationFk = $configurationFk; return $this; } public function getConfigurationFk() { return $this->configurationFk; } }
Entity \ CoreCodes (source of potential values โโfor ConfigurationsFeatures-> featureFk)
use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; /** * Lynux\AssetBundle\Entity\Core\Codes * * @ORM\Table(name="core_codes") */ class Codes { /** * @var integer $id * * @ORM\Column(name="id", type="integer", nullable=false, unique=true) * @ORM\Id * @Assert\NotBlank(message="ID cannot be blank!") * @Assert\Regex(pattern="/^\d+$/", match=true, message="ID must be an integer!") * @Assert\MinLength(limit=8, message="ID must be 8 digits in length!") * @Assert\MaxLength(limit=8, message="ID must be 8 digits in length!") */ private $id; // ... various properties, not applicable to question ... /** * Set id * * @param integer $id * @return Codes */ public function setId($id) { $this->id = $id; return $this; } /** * Get id * * @return integer */ public function getId() { return $this->id; } // ... getters and setters for other properties ... }
Type \ FormConfigurations
use Doctrine\ORM\EntityRepository; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class FormConfigurations extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $features = $this->features; // ... builders for other properties ... $builder->add( 'features', 'entity', array( 'class' => 'LynuxAssetBundle:Core\Codes', 'property_path' => false, 'query_builder' => function(EntityRepository $er) use ($features) { return $er->createQueryBuilder('u') ->where('u.submodule = :submodule') ->setParameter('submodule', 'feature'); }, 'expanded' => true, 'multiple' => true, 'property' => 'title',)); } public function getName() { return 'FormConfigurations'; } public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults( array( 'data_class' => 'Lynux\AssetBundle\Entity\Core\Configurations',)); } }
Controller \ ConfigurationsController :: createAction ()
public function createAction(Request $request) { $config = $request->getSession()->get('configuration'); $manage = $this->getDoctrine()->getEntityManager(); $entity = new Configurations(); $form = $this->createForm(new FormConfigurations($features), $entity); $failed = null; $features = $manage ->getRepository('LynuxAssetBundle:Core\Codes') ->findBySubmodule('feature'); if ('POST' == $request->getMethod()) { $form->bind($request); if ($form->isValid()) { $status = $manage ->getRepository('LynuxAssetBundle:Core\Codes') ->findOneById(10103022); $entity->setToken($entity->getName()); $entity->setStatusFk($status); $entity->setCreateAccountFk($this->getUser()); $features = $form->get('features')->getData(); foreach($features as $feature) { $addFeature = new ConfigurationsFeatures(); $addFeature->setConfigurationFk($entity); $addFeature->setFeatureFk($feature); $manage->persist($addFeature); } $manage->persist($entity); $manage->flush(); return $this->redirect($this->generateUrl( 'CoreConfigurationsConfirm', array( 'code' => 'create', 'token' => $entity->getToken(),))); } else { $failed = true; } }
Controller \ ConfigurationsController :: UpdateAction ()
public function updateAction(Request $request, $token) { $manage = $this->getDoctrine()->getEntityManager(); $entity = $manage ->getRepository('LynuxAssetBundle:Core\Configurations') ->findOneByToken($token); $form = $this->createForm(new FormConfigurations($features), $entity); if ('POST' == $request->getMethod()) { $form->bind($request); if ($form->isValid()) { $currentFeatures = $manage ->getRepository('LynuxAssetBundle:Core\ConfigurationsFeatures') ->findByConfigurationFk($entity); foreach($currentFeatures as $currentFeature) { $manage->remove($currentFeature); } $features = $form->get('features')->getData(); foreach($features as $feature) { $addFeature = new ConfigurationsFeatures(); $addFeature->setConfigurationFk($entity); $addFeature->setFeatureFk($feature); $manage->persist($addFeature); } $manage->flush(); } }