2

I'm getting a foreign constraint violation when trying to cascade delete entities having one-to-one and one-to-many bidirectional relations. Here are my four entities related this way : the "User" object may have zero or one "Contact". Contact may have zero or one "Address" and zero or many "Telephone". But "Contact" must be related to a "User" entity, as well as "Address" and "Telephon"e with a "Contact" entity.

My aim is, when I delete a "User" all the child objects are cascade deleted too ("Contact", "Address" and "Telephone"). However, when I delete a child object, I just want its reference id in the parent entity to be set to NULL.

I've tried several ways including the options onDelete="CASCADE" and onDelete=NULL but I still get the foreign constraint violation error.

User entity

class User { /** * @var integer * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ protected $id; /** * Contact * * @ORM\OneToOne(targetEntity="Contact", mappedBy="user", cascade={"persist", "remove"}) * @ORM\JoinColumn(nullable=true) */ private $contact; ... } 

Contact entity

class Contact { /** * @var integer * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * Address * * @ORM\OneToOne(targetEntity="Address", mappedBy="contact", cascade={"persist", "remove"}) * @ORM\JoinColumn(nullable=true) */ private $address; /** * Telephones * * @ORM\OneToMany(targetEntity="Telephone", mappedBy="contact", cascade={"persist", "remove"}) * @ORM\JoinColumn(nullable=true) */ private $telephones; /** * User * * @ORM\OneToOne(targetEntity="User", inversedBy="contact", cascade={"persist"}) * @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=false) */ private $user; /** * Constructeur */ public function __construct() { $this->telephones = new ArrayCollection(); } ... } 

Address entity

class Address { /** * @var integer * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @ORM\OneToOne(targetEntity="Contact", inversedBy="address", cascade={"persist"}) * @ORM\JoinColumn(name="contact_id", referencedColumnName="id", nullable=false) */ private $contact; ... } 

Telephone entity

class Telephone { /** * @var integer * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @ORM\ManyToOne(targetEntity="Contact", inversedBy="telephones", cascade={"persist"}) * @ORM\JoinColumn(name="contact_id", referencedColumnName="id", nullable=false) */ private $contact; ... } 
2
  • what is the error exactly Commented Sep 2, 2014 at 11:40
  • "Cannot delete or update a parent row: a foreign key constraint fails (eds.eds_contact, CONSTRAINT FK_E2314CF8FB88E14F FOREIGN KEY (user_id) REFERENCES eds_user (id))" Commented Sep 2, 2014 at 12:24

2 Answers 2

1

Try this configuration. I have only made changes to the @ORM\JoinColumn annotations by adding onDelete="CASCADE". This uses the built in database cascading so you will need to update your schema. I have also removed some extraneous @ORM\JoinColumn(nullable=true) annotations on non owning sides of relations. These had no effect and were only misleading.

User entity

class User { /** * @var integer * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ protected $id; /** * Contact * * @ORM\OneToOne(targetEntity="Contact", mappedBy="user", cascade={"persist", "remove"}) */ private $contact; ... } 

Contact entity

class Contact { /** * @var integer * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * Address * * @ORM\OneToOne(targetEntity="Address", mappedBy="contact", cascade={"persist", "remove"}) */ private $address; /** * Telephones * * @ORM\OneToMany(targetEntity="Telephone", mappedBy="contact", cascade={"persist", "remove"}) */ private $telephones; /** * User * * @ORM\OneToOne(targetEntity="User", inversedBy="contact", cascade={"persist"}) * @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=false, onDelete="CASCADE") */ private $user; /** * Constructeur */ public function __construct() { $this->telephones = new ArrayCollection(); } ... } 

Address entity

class Address { /** * @var integer * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @ORM\OneToOne(targetEntity="Contact", inversedBy="address", cascade={"persist"}) * @ORM\JoinColumn(name="contact_id", referencedColumnName="id", nullable=false, onDelete="CASCADE") */ private $contact; ... } 

Telephone entity

class Telephone { /** * @var integer * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @ORM\ManyToOne(targetEntity="Contact", inversedBy="telephones", cascade={"persist"}) * @ORM\JoinColumn(name="contact_id", referencedColumnName="id", nullable=false, onDelete="CASCADE") */ private $contact; ... } 
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks Tom, it works fine ! I feared removing the JoinColumn annotation on the non-owning side could remove the bidirectional relation. I was wrong...
0
$user->setContact(null); $contact->setUser(null); $em->remove($user); $em->remove($contact); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.