1

In my app, when users sign up I have to send them an email with a validation key, as usually happens on most websites, I'm trying to do this with Doctrine but I can’t get it to work when I try to persist() the user.

First of all, I think the correct way in this case is to use a OneToOne unidirectional relationship, but I don’t know if it would be better to use a bidirectional one. I've tried both and I always get an error.

I have read these two questions carefully:

One to one relationship on two tables sharing primary key

Doctrine one-to-one unidirectional

As well as this part of the documentation. When I validate the schema (php bin/console doctrine:schema:validate) everything is fine.

class Usuario {
  /**
   * @ORM\Column(name="id", type="integer")
   * @ORM\Id
   * @ORM\GeneratedValue(strategy="IDENTITY")
   */
  private $id;

  // ...
}

class ClaveVal {
  /**
   * @ORM\Id
   * @ORM\OneToOne(targetEntity="Usuario")
   */
  private $usuario;

  /**
   * @ORM\Column(name="clave", type="string", length=20, nullable=false)
   * @Assert\NotBlank()
   */
  private $clave;

  // ...
}

Which is quite similar to this.

Now, I'm trying to persist() a new Usuario and a new ClaveVal for this usuario like this:

$usuario = new Usuario();
// Add usuario attributes
$claveVal = new ClaveVal();
$claveVal->setUsuario($usuario);
$claveVal->setClave(‘123456’);
$em->persist($usuario);
$em->persist($claveVal);

But I get this error:

The given entity of type 'AppBundle\Entity\ClaveVal' (AppBundle\Entity\ClaveVal@000000007020f28f0000000031d5c8c6) has no identity/no id values set. It cannot be added to the identity map

I know why this happens. This works perfectly:

  $em->persist($usuario);
  $em->flush();
  $em->persist($claveVal);
  $em->flush();

But I don't want to do that because I want it to be a unit of work using flush() only once.

Besides, as the author of the post I linked above says, it should be Doctrine's job to flush() at the right moment to get the id.

So, how can I achieve this using flush() only once (and without using transactions or listeners, I'm sure there is an easier way to do this)? Would it be better to use a bidirectional OneToOne relationship? As I said, I tried it too but I got the same error.

Thanks in advance.

DandyCC
  • 353
  • 1
  • 6
  • 20
  • might look into the doctrine cascade functionality: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/working-with-associations.html#transitive-persistence-cascade-operations – Andrew Nolan Jul 05 '17 at 22:11
  • Your ClaveVal Entity should have primary key. This is for sure. – Artur Yukhatov Jul 06 '17 at 07:47
  • I triied with `@ORM\OneToOne(targetEntity="Usuario", cascade={"persist", "remove"})`, but didn't work. @Artur, ClaveVal has usuario as PK and FK – DandyCC Jul 06 '17 at 15:22
  • 1
    You need to specify the join column on either the `Usuario` entity or the `ClaveVal` entity, otherwise Doctrine has no idea how these two entities are related. – Jason Roman Jul 07 '17 at 05:16

0 Answers0