Deleting

Objectiphy can be used to delete database records and remove relationships between them. If you have referential integrity defined in your database (foreign key constraints), attempts to remove entities or relationships can result in errors, and you will have to ensure your constraints are set up correctly, and that you delete things in the right order (do not use orphan removal or cascade deletes on both sides of a relationship if you have referential integrity in place, or you will likely have issues when trying to delete).

There is a safety and performance feature in Objectiphy that allows you to disable deletes - either for relationships, or entities (or both). There are some performance savings by disabling deletes, and of course if you disable them, you don't risk deleting records by accident. You might therefore decide to disable deletes by default and only re-enable them as and when you need to delete things. You can disable or enable deletes via a configuration option.

The reason deletes are not disabled by default is because that would probably be counter-intuitive and confusing for new users, as it is not obvious that you would have to enable deletes before use (and the performance savings of disabling deletes are not usually particularly significant unless you disable the cache).

Removing Relationships

To remove a one-to-one or many-to-one relationship, you can simply set the property on the parent object that relates to the child object to null (or set the parent property on the child object to null if the child owns the relationship). When you save the entity, Objectiphy will see that the relationship has been deleted, and will set the foreign key value to null in the database. This will have the effect of orphaning the child object - it will still exist in the database, but will have no parent (see orphan removal, below).

Note: if the child owns the relationship (ie. the table that stores the child contains a foreign key pointing to the parent), you must remove the relationship from the child and save the child entity - if you save the parent entity, the relationship will not be removed (as Objectiphy will helpfully notice that the parent is not populated on the child and re-populate it for you). For a full explanation of this, see the troubleshooting page.

To remove a one-to-many or many-to-many relationship, you can either set the entire collection or array of child objects to null, in the same way as you would with a one-to-one relationship, or if you just want to select certain children to be removed, you can just remove them from the array or collection. When you save the entity then, Objectiphy will see that some children have been removed, and will set the foreign key on the removed children to null - again, this will have the effect of making those child records orphans.

Orphan Removal

In cases where a child needs to be deleted when it is removed from its parent (a 'private' parent/child relationship), or when its parent is deleted and the child has no other parent - ie. where it cannot be moved to another parent, and cannot exist in isolation (maybe line items on an invoice, for example), you can use orphan removal to cause orphaned child objects to be deleted from the database. This can be specified in the mapping definition, by setting the orphanRemoval attribute to true in the mapping definition. Note however, that Objectiphy's behaviour is different to that of Doctrine when it comes to orphan removal, as described below.

Before removing orphans on many-to-one or many-to-many relationships, Objectiphy will first check to make sure the child is not associated with any other parent. This check will only occur for other parents involved in the same relationship. If a completely different parent class, or a different property on the same parent class has a reference to the child, Objectiphy will not know about that, and will assume it is safe to delete. In such cases, the relationship is not truly private, so you should not use orphan removal, but handle the deletion yourself. This is different from Doctrine in that Doctrine does not do any checks at all, and just blindly deletes the child, even if it has been assigned to another parent.

Orphan removal (and cascading deletes) will only occur if you call the saveEntity, saveEntities, deleteEntity or deleteEntities methods - passing in either the entity or entities to save/delete, or object references representing them. If you execute a custom delete query directly, Objectiphy will not interfere, so you will have to manage orphan removal and cascading deletes yourself in that case (in practice, this means you might encounter foreign key constraint failures when deleting via a delete query, but not when you call deleteEntity).

Deleting Entities

You can delete entities using the deleteEntity or deleteEntities methods on the repository, and passing in the entity to delete, or an objejct reference (created using the $repository->getObjectReference method) that refers to it. If deletes are disabled, this will result in an Exception being thrown (unless you specifically tell it not to, by setting the $exceptionIfDisabled flag to false). If you don't already have an instance of the entity you want to delete, just its primary key value, using an object reference avoids an unnecessary database lookup. For more complex delete requirements, you can use a delete query to delete one or more records using criteria (but be aware that cascade deletes and orphan removal will not take effect for delete queries).

Cascade Deletes

In cases where child objects need to be deleted if the parent is deleted, you can specify that deletes should be cascaded in the mapping definition, by setting the cascade attribute on a Doctrine mapping definition to either 'REMOVE' or 'ALL', or by setting the cascadeDeletes attribute to true on the Objectiphy column definition. Even if that is set though, you still have the option of disabling cascades at the time you call deleteEntity, by passing true as the second parameter. If possible though, it is usually preferable to set up cascading deletes in your database (if supported by your database engine), as that will be quicker and will work even if records are deleted manually outside of Objectiphy.

Objectiphy will throw an exception if you try to set cascade deletes to true on a many-to-one or many-to-many relationship. This is because by definition, the child could have an additional parent. Orphan removal is allowed however (and would only occur if the child did not belong to any other parents) - see above.

Cascading deletes (and orphan removal) will only occur if you call the deleteEntity or deleteEntities methods - passing in either the entity or entities to delete, or object references representing them. If you execute a delete query directly, Objectiphy will not interfere, so you will have to manage orphan removal and cascading deletes yourself in that case.

What is the difference between Orphan Removal and Cascade Deletes?

Orphan removal occurs when a relationship is deleted, even if no entities are deleted (but also occurs if a parent entity is deleted), but on many-to-one and many-to-many relationships, a check is made to ensure the child does not belong to another parent before it can be deleted. Cascade deletes occurs when a parent entity is deleted, but does not occur if a relationship is deleted, and (as explained above), is not allowed on many-to-one or many-to-many relationships.

For example, imagine a Customer entity with a child property called 'orders' which holds a collection of Order entities. The following table indicates what results will occur with orphan removal or cascade deletes enabled:

Last updated