Reputation: 479
I have a 'person' entity that has a manyToOne relationship with a 'city' entity:
Here's the person's relationship mapping:
/**
* @ORM\ManyToOne(targetEntity="City", inversedBy="persons", cascade={"persist"})
*/
private $city;
and city's:
/**
* @ORM\OneToMany(targetEntity="Person", mappedBy="city")
*/
private $persons;
I use the basic Symfony 2 'person' controller generated by doctrine:generate:crud:
$entity = new Person();
$form = $this->createForm(new PersonType(), $entity);
$form->bind($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
}
The PersonType form type instantiates a CityType
class PersonType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('city', new CityType())
->add('firstname')
->add('lastname')
->add('gender')
...
The CityType form type has a single text field
class CityType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('cityname', 'text');
}
}
When I submit the form, the Person entity is created, as well as the City entity, thanks to the cascade={"persist"}.
The problem arrises when I fill out the form with a city name that already exists in the DB, Doctrine creates another entry with the same city name.
Is there a simple way Doctrine could detect that, and use the existing city_id in the Person table?
Upvotes: 3
Views: 7928
Reputation: 5158
As @vadim said, you must use datatransformer. It might be confusing at start but after ~30 minutes you will learn it. Keep in mind that around the world, you will have many cities with same name.
The best solution is this; in that text field, user would type a name like Belgrade, Montana, Usa
(btw; Belgrade is capital of Serbia, just giving you an example of cities with same name). Datatransformer will read DB and find the correct city of Belgrade that you could link with.
After you do this (and it is very simple), that you could build auto-completion for that field. @artworkad suggestion is overly complicated and will bring more problems later.
Upvotes: 2
Reputation: 70406
One solution is, don't cascade persisting of entities. I.e.
if ($form->isValid()) {
$data = $form->getData();
$em = $this->getDoctrine()->getEntityManager();
$city = $em->getRepository('YourBundle:City')
->findOneByCityname($data['cityname']);
if($city == null){
$city = new City();
$city->setName($data['cityname']);
$em->persist($city);
$em->flush();
}
$entity->setCity($city);
$em->persist($entity);
$em->flush();
}
Upvotes: 2