Doctrine Class Table Inheritance can not remove() entity

1.2k Views Asked by At

I try to implement Doctrine's Class Table Inheritance. My Application needs a User Entity that is used to authenticate the user through Symfony's security system. On top of that, my application needs a special kind of User, a Doctor. Below you can find excerpts of my Entity classes.

User class (Base):

/**
 * @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
 * @ORM\Table(name="user")
 * @UniqueEntity("email")
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="discr", type="string")
 * @ORM\DiscriminatorMap({"user" = "User", "doctor" = "Doctor"})
 */
class User implements UserInterface, \Serializable, EquatableInterface {

/**
 * @ORM\Id()
 * @ORM\Column(name="id", type="uuid_binary")
 * @ORM\GeneratedValue(strategy="CUSTOM")
 * @ORM\CustomIdGenerator(class="Ramsey\Uuid\Doctrine\UuidGenerator")
 * @JMS\Type("uuid")
 */
private $id;

// More fields that are used for authenticating a user (password, email, etc.)

}

Doctor Entity extends User:

/**
 * @ORM\Entity(repositoryClass="AppBundle\Repository\DoctorRepository")
 * @ORM\Table(name="doctor")
 * @ORM\HasLifecycleCallbacks()
 */
class Doctor extends User {

 /**
 * @ORM\Column(name="title", type="string")
 */
private $title;

// More fields that extend the User Entity

}

Weirdly I can neither delete Users nor the Doctors using the EntityManager's remove() method, which I have never had problems with. When I use the method no errors are thrown or logged, but the Entity instance remains in the database.

// This does not work. The user stays persisted in the database.
public function deleteUserAction($id) {
    $em = $this->getDoctrine()->getManager();
    $user = $em->getRepository('AppBundle:User')->find($id);
    if(empty($user)) {
        return new View('User not found', Response::HTTP_NOT_FOUND);
    }
    $em->remove($user);
    $em->flush();
    return new View('Deleted user', Response::HTTP_OK);
}

I found a workaround using a manual query to delete the object from the database.

// This works. The User is deleted from the database.
// If the user is a doctor the doctor referencing the user id is also
// deleted.
$qb = $em->createQueryBuilder()
        ->delete('AppBundle:User', 'u')
        ->where('u.id = :id')
        ->setParameter('id', $id, 'uuid_binary');
$qb->getQuery()->execute();
return $user;

So I could just use the code above, but I still would like to know what causes this problem to occur? Thanks in advance!

2

There are 2 best solutions below

1
Łukasz D. Tulikowski On

When you do not use the SchemaTool to generate the required SQL you should know that deleting a class table inheritance makes use of the foreign key property ON DELETE CASCADE in all database implementations. A failure to implement this yourself will lead to dead rows in the database.

Reference: Doctrine 2 documentation:

Running this SQL query like following may solve your problem

ALTER TABLE user 
ADD CONSTRAINT fk_user_1
FOREIGN KEY (id_user)
REFERENCES doctor (id_user)
ON DELETE CASCADE
ON UPDATE NO ACTION;
0
Jasson Rojas On