Reinherd
Reinherd

Reputation: 5504

How would you set the Cascade on removal?

I'm having some issues while deleting some objects, because those objects have other objects related to them.

For example. I've an entity named Home. This entity has some fields like name and description, aswel as id.

And then, I've an entity named Citizen which contains name, surname, home. This last field is directly related to Home.

So if I try to remove a HOME object, it crashes because there are some foreign key relating this object. What I'm doing at the moment, is searching for Citizens, and removing them, but this is not the best way to achieve this.

I know there's an annotation like "CASCADE" but I don't know where to place this annotation.

Where do I've to set this annotation to achieve what I'm trying to do?

Thanks.

Upvotes: 1

Views: 91

Answers (2)

Nicolai Fröhlich
Nicolai Fröhlich

Reputation: 52523

There are actually two ways of achieving your goal. You can use ORM level and Database level cascades.

ORM Level

// Home Entity

/**
 * @comment The owning side has to use the inversedBy attribute of ManyToOne
 * 
 * @ManyToOne(targetEntity="Citizen", inversedBy="home", cascade={"remove"})
 */
 protected $citizens;

 // ...

Database Level

// Home Entity

/**
 * onDelete="CASCADE" is used on the joinColumn 
 * It will add On Delete Cascade to the foreign key column in the database.
 * 
 * @ManyToOne(targetEntity="Citizen", inversedBy="home", cascade={"remove"})
 * @ORM\JoinColumn(name="citizen_id", referencedColumnName="id", onDelete="CASCADE")
 */
 protected $citizens;

 // ...

Attention

You have to be careful where you set your cascade option.

You most likely don't want to have doctrine remove your owning side of the relation ( in this case delete the Home if you remove a citizen - therefore only set it on your Home entity ).

Alesh's example is wrong in your use case as mappedBy is always the inverse side of a relationship!

In your case Home will be the owning side as one Home will own multiple Citizens. Now if you delete Home you want your Citizens to be homeless ( aka removed ).

Doctrine also only tracks the owning side of the relation for changes, now if you add a citizen to the collection ( for example with a collection form type ) with ...

$home->addCitizen($citizen);

... you likely want your citizen to be automatically persisted ( with cascade persist set ) when calling

$em->flush();

Upvotes: 2

Ales
Ales

Reputation: 908

In your home entity, you should have field, which contains all citizens.

    /**
     *
     * @OneToMany(targetEntity="Citizen", mappedBy="home", cascade={"remove"})
     */
     protected $citizens;

Upvotes: 3

Related Questions