Is there a method / plugin which allows a cascading deletion?

I'm working on an author agency site and have set up 2 channels, Authors and Books. The Book entry section has a Field set to Entries which allows me to specify the Author/s from the Author Channel.

What I want to happen is, when an Author is deleted from the system so are all their books (unless the books has more than 1 author).


You can use the onBeforeDeleteEntry event in an 'init' method defined in your plugin's main file to: intercept the delete process; retrieve the related books; check each book for more than one author; and if only one author, delete the book.

Not tested.

public function init()

    craft()->on('entries.onBeforeDeleteEntry', function(Event $event)
        $entry = $event->params['entry'];
        $section = $entry->getSection()->handle;

        if ($section == 'myAuthorsSectionHandle') {

            // get related book entries
            $criteria = craft()->elements->getCriteria(ElementType::Entry);
            $criteria->section   = 'myBooksSectionHandle';
            $criteria->relatedTo = array(
                'targetElement' => $entry,
                'field'         => 'myBooksSectionRelatedAuthorsFieldHandle'
            $books = $criteria->find();

            foreach ($books as $book) {
                $authors = $book->myBooksSectionRelatedAuthorsFieldHandle;
                if (count($authors) == 1) {
                    // delete the book entry
                } else if (count($authors) > 1) {
                    // decide what you want to do when more than one author found.
                    // use `$event->performAction = false;` to cancel the original delete operation if you need to
                } else {
                    throw new Exception('No authors found. This is impossible, my code must have an error somewhere.');



Update It appears as though the onBeforeDeleteEntry event does not get raised when deleting multiple entries from the entry index page (as I would think it should), presumably because it is using elements->deleteElementById() to do so, thus bypassing the EntriesService event. In any rate, you might try the following instead.

craft()->on('elements.onBeforeDeleteElements', function(Event $event)
    $elementIds = $event->params['elementIds'];

    foreach ($elementIds as $elementId) {
        $element = craft()->elements->getElementById($elementId);
        if ($element->getElementType() == 'Entry') {
            $entry = $element;
            $section = $entry->getSection()->handle;
            if ($section == 'myAuthorsSectionHandle') {
               // rest of the code as above
  • 1
    Someone please check that I got the 'targetElement' and 'field' defined correctly. I always get confused. – Douglas McDonald Feb 12 '15 at 22:06
  • This looks great Douglas. I kinda follow it but I've never written a plugin for Craft, I wouldn't know where to start. In fact this is my first project using it. – Dr_Codswallop Feb 12 '15 at 22:31
  • 1
    It's really easy. I would recommend starting with the BusinessLogic Template plugin. Just download that and install it (place in plugins folder, goto settings, install, and activate). Then open up the main businessLogic.php file and paste in the method above. That should do it. Of course, might need to debug what I wrote. If you see an error, let me know and I'll try and fix it. – Douglas McDonald Feb 12 '15 at 22:34
  • 2
    "Someone please check..." done! ;) – carlcs Feb 12 '15 at 22:45
  • OK, so I think I had to make a couple of syntax amendments - semicolons at the end of $criteria->section = 'books'; & $criteria->section = 'authors'; – Dr_Codswallop Feb 12 '15 at 22:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.