-1

I am trying to create a form which will collect a list of facilities and contact information:

The issue is I would like to have the facility, and exactly 4 contacts of different types. I realize I could make this work separately by making each contact a property on the Facility entity but it feels like it would be cleaner and easier to use the data later if it is in a collection.

You'll notice in the FacilityType class, I use $builder->create to add a sub-form which gives me the structure I'm expecting but I get an error when I try to persist. "A new entity was found through the relationship 'AppBundle\Entity\Facility#contacts' that was not configured to cascade persist operations for entity:...."

Thanks. My code is below.

The Facility entity:

<?php 
namespace AppBundle\Form;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
class Facility
{
  /**
   * @ORM\Column(length=200)
   */
  public $name;
  /**
   * @ORM\OneToMany(targetEntity="FacilityContact", mappedBy="facility")
   */
  public $contacts;
  public function __construct()
  {
    $this->contacts = new ArrayCollection;
  }
}

The FacilityContact entity:

<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
class FacilityContact
{
  /**
   * @ORM\ManyToOne(targetEntity="facility", inversedBy="contacts")
   */
  public $facility;
  /**
   * @ORM\Column(type="string", length=50)
   */
  public $contactType;
  /**
   * @ORM\Column(type="string", length=200)
   */
  public $name;
  /**
   * @ORM\Column(type="string", length=100)
   */
  public $email;
  /**
   * @ORM\Column(type="string", length=15)
   */
  public $phone;
}

Facility Form

class FacilityType extends AbstractType
{
  /**
   * @param FormBuilderInterface $builder
   * @param array $options
   */
  public function buildForm(FormBuilderInterface $builder, array $options)
  {
    $centre = $this->centre;
    $builder->add('name', 'text', array("label"=>"Facility Name");

    $contacts = $builder->create("contacts", "form");
    $contacts
      ->add("radonc", new FacilityContactType("radonc"), array("label" => "Radiation Oncologist"))
      ->add("physicist", new FacilityContactType("physicist"), array("label" => "Physicist Responsible"))
      ->add("radtherapist", new FacilityContactType("radtherapist"), array("label" => "Radiation Therapists"))
      ->add("datamanager", new FacilityContactType("datamanager"), array("label" => "Data manager"))
      ;        
    $builder->add($contacts);
  }
  public function setDefaultOptions(OptionsResolverInterface $resolver)
  {
    $resolver->setDefaults(array(
      'data_class' => 'AppBundle\Entity\Facility'
    ));
  }
  public function getName()
  {
     return 'appbundle_facility';
  }
}

FacilityContact form

<?php
namespace AppBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class FacilityContactType extends AbstractType
{
  private $contactType;
  public function __construct($contactType)
  {
    $this->contactType = $contactType;
  }
  /**
   * @param FormBuilderInterface $builder
   * @param array $options
   */
  public function buildForm(FormBuilderInterface $builder, array $options)
  {
    $builder
      ->add('contactType', 'hidden', array("read_only" => true, "data"=>$this->contactType))
      ->add('name', 'text', array("required" => false))
      ->add('phone', 'text', array("required" => false))
      ->add('email', 'email', array("required" => false))
    ;
  }

  /**
   * @param OptionsResolverInterface $resolver
   */
  public function setDefaultOptions(OptionsResolverInterface $resolver)
  {
    $resolver->setDefaults(array(
      'data_class' => 'AppBundle\Entity\FacilityContact'
    ));
  }
  /**
   * @return string
   */
  public function getName()
  {
    return 'appbundle_facilitycontact';
  }
}
Teddy
  • 53
  • 5

1 Answers1

0

Doctrine is trying to tell you that there are one or more objects, that it does not know about, because they were not persisted into the database.

This happens, because in the FacilityForm you are using the FacilityContactForm, that creates 4 new FacilityContact entities. You are trying to persist only the Facility entity without the other 4 entities, it wouldn't be any problem, but there is a relationship between them and in the database the Facility entity doesn't have its FacilityContacts.

You can resolve this in two ways:

  • using the cascade options, something like this: @ORM\OneToMany(targetEntity="FacilityContact", mappedBy="facility", cascade={"persist"}), basically this tells doctrine that it should persist also the FacilityContacts entities, you can read more at: http://doctrine-orm.readthedocs.org/en/latest/reference/working-with-associations.html, and you also have here some explanation about cascade: Doctrine Cascade Options for OneToMany.

  • another option is to create before the Facility entity with the contact collection empty, persist it to the database, and then to persist the FacilityContacts to the database and add them to the contact array with the add method, and then only call $em->update(), because doctrine knows and is monitoring any changes about the Facility entity.

Community
  • 1
  • 1
flore77
  • 41
  • 4