I have a plugin that needs to do something when an entry is deleted. I've recently discovered that the entries.deleteEntry event is not fired when deleting bulk entries (the list view with checkboxes) in the Control Panel (CP). Instead, an elements.onPerformAction event is fired (you can also listen for onBeforePerformAction).

Now that I know that these are the events that are fired when deleting an entry from the list view in the CP, and that I'm working with an Element event instead of a Entry event, I'm struggling to access the type of information I need.

I would like to know...

  1. what type of action is being performed on the element? (Save, Delete, etc.)

  2. how do I identify the entry that the action is being performed on?

1 Answer 1


It appears that when one or more Entries (or other types of content) are manipulated (in my case, deleted) from the bulk edit view in the Control Panel, the type of events that are triggered are Element events, rather than Entry events.

If you refer to the Craft documentation on elements.onPerformAction, you can see that the 2 params you get access to are action and criteria.

Here's how I was able to find what I needed when working with elements.onPerformAction and the elements.onBeforePerformAction events.

  1. What type of action is being performed on the element? (Save, Delete, etc.)

I was able to capture what type of action was being being performed on my element by looking at the "action" param of the event. Using the following code output the action that was taking place:

$action = $event->params['action']->classHandle; //Outputs 'Delete'

This bit of code will output the string 'Delete'. Perfect.

  1. How do I identify the entry that the action is being performed on.

What I learned is that, when working with an Element event, you're not just working with a single entry. You're potentially working with many Entries, or rather "Elements" to be more specific. Because of this, you can't just grab the Element being manipulated in the same style you can with an Entries event.

$entry = $event->params['entry']; won't work here.

This brings us to the "criteria" param of the Element event.

You can simply grab the "criteria" param of the event to get the elements that the event is taking place on. This param contains an ElementCriteriaModel object.

Viewing the class reference for ElementCriteriaModel shows us what we can do with this object. In my case, I can simply use ->find() on it to get all of the elements I'm working with.

$elements = $event->params['criteria']->find();

I now have an array of the Elements having actions taken on them, stored in $entries.

Now that I have both the type of action and the elements, I have what I was needing to move forward.

Here are my event listeners in full context. One handles a entries.deleteEntry event, and the other handles a elements.onBeforePerformAction event.

craft()->on('entries.deleteEntry', function(Event $event) {
    $entry = $event->params['entry'];

craft()->on('elements.onBeforePerformAction', function(Event $event) {
    $action = $event->params['action']->classHandle; //Outputs 'Delete'
    $elements = $event->params['criteria']->find(); //Array of Elements
    if ($action == 'Delete') {
        foreach ($elements as $element) {

It's important to remember that since we could theoretically be working with many types of Elements (Entries, Assets, Categories, Users, etc.), rather than just Entries, we may need to validate that we're working on the right types of Elements before we operate on them. Since I have multiple event handlers calling my deleteOrgCustomerAddress() service, I did this validation check there.

public function deleteOrgCustomerAddress($element)

    // Make sure we're working with an entry in the organizations section
    if ($element->elementType !== 'Entry' && $element->section->handle !== 'organizations') {

    // We are good to go! Do stuff with the Entry...

Thanks to @lindsey-d for some help along the way!

  • Wow, that's way better than what I was going to answer. :)
    – Brad Bell
    Commented Sep 17, 2016 at 21:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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