<p>You can find out what the stack trace is (who is calling you) by putting something like this in your anonymous function:</p>

<pre class="lang-php prettyprint-override"><code>                try {
                    throw new \Exception();
                } catch (\Exception $e) {
                    Craft::debug(
                        'EVENT_AFTER_SAVE_ELEMENT '.$e-&gt;getTraceAsString(),
                        __METHOD__
                    );
                }
</code></pre>

<p>Then search on <code>EVENT_AFTER_SAVE_ELEMENT</code> in your <code>web.log</code></p>

CC BY-SA 4.0
2019-08-19T01:10:46.257Z
Great tip! Thanks, Andrew!
Wei
CC BY-SA 4.0
2019-08-16T03:36:42.057Z
2019-08-16T03:36:42.057Z
andrew.welch
<p>After using Andrew's <a href="https://craftcms.stackexchange.com/a/31236/7136">debugging tip</a>, I found out one event was triggered by saving the element itself, and the other was triggered by saving the revision of the element. So I modified my event listener to be like the following, and it solved the double-up issue:</p>

<pre><code>Event::on(
    \craft\services\Elements::class,
    \craft\services\Elements::EVENT_AFTER_SAVE_ELEMENT,
    function (\craft\events\ElementEvent $event) {
        $element = $event-&gt;element;
        if(
            $element instanceof \craft\elements\Entry // is entry
            &amp;&amp; $element-&gt;getSection()-&gt;handle == 'pages' // is in 'pages' section
            &amp;&amp; !$element-&gt;getIsRevision() // is not revision
            &amp;&amp; !$element-&gt;getIsDraft() // is not draft
            // &amp;&amp; !$element-&gt;propagating // not during propagating (avoid batch propagating)
            // &amp;&amp; !$element-&gt;resaving // not during resaving (avoid batch resaving)
        ) {
            // --------------- My Stuff -------------- //
            // $entry is the $element
            // $isNew = $event-&gt;isNew
            // ...
        }
    }
);
</code></pre>

<p>Depending on what you are trying to do in the event handler, you might want to toggle some if conditions. For example, you might want to avoid the same handler executed hundreds of times during a batch of <a href="https://docs.craftcms.com/api/v3/craft-services-elements.html#method-resaveelements" rel="noreferrer">re-saving action</a> which is triggered when a section's setting is updated and Craft automatically re-saves all the entries under the section. In this case, you might consider having a separate EVENT_AFTER_RESAVE_ELEMENTS event handler.</p>

CC BY-SA 4.0
2019-08-19T11:56:36.000Z
Nicely done tracking it down! If you're using Craft 3.2, there's a helper: `ElementHelper::isDraftOrRevision($element)`
andrew.welch
CC BY-SA 4.0
2019-08-20T04:16:13.837Z
@andrew.welch ahh, good to know. Thanks!
Wei
CC BY-SA 4.0
2019-08-19T01:17:53.733Z
2019-08-19T02:06:11.730Z
2019-08-19T02:06:11.730Z
Wei
<p>I had this weird issue, not sure if that happens to you guys or not.</p>

<p>I'm trying to catch the 'after entry is saved' event, using the following code in my custom module's init() function (The module's code is generated by <a href="https://pluginfactory.io/" rel="noreferrer">pluginfactory.io</a>):</p>

<pre><code>Event::on(
    \craft\services\Elements::class,
    \craft\services\Elements::EVENT_AFTER_SAVE_ELEMENT,
    function (\craft\events\ElementEvent $event) {
        $element = $event-&gt;element;
        if($element instanceof \craft\elements\Entry) {
            // Craft::info('Entry saved: ' . $element-&gt;title, __METHOD__);
        }
    }
);
</code></pre>

<p>It seems to work by testing on saving an entry in the CP, but the weird thing is this event seems to be triggered twice according to the log:</p>

<pre><code>2019-08-16 12:21:52 [-][1][-][info][modules\testmodule\{closure}] Entry saved: Document translation
2019-08-16 12:21:52 [-][1][-][info][modules\testmodule\{closure}] Entry saved: Document translation
2019-08-16 12:21:52 [-][1][-][info][application] $_GET = [
    'p' =&gt; 'admin/entries/pages/234-document-translation'
]
</code></pre>

<p>I also tried Andrew's answer in this post: <a href="https://craftcms.stackexchange.com/a/26815/7136">https://craftcms.stackexchange.com/a/26815/7136</a>, but same thing happened.</p>

<pre><code>Event::on(
    \craft\elements\Entry::class,
    \craft\elements\Entry::EVENT_AFTER_SAVE,
    function (\craft\events\ModelEvent $event) {
        Craft::debug(
            '\craft\elements\Entry::EVENT_AFTER_SAVE',
            __METHOD__
        );
    }
);
</code></pre>

<p>I certainly don't want my custom code to be executed twice. Is this a bug or an expected behavior?</p>

<p>Craft version: 3.2.10</p>

<craft3><events>
EVENT_AFTER_SAVE_ELEMENT triggered twice after saving an entry
# EVENT_AFTER_SAVE_ELEMENT triggered twice after saving an entry

(Asked by: username_0 on 2019-08-16)

I had this weird issue, not sure if that happens to you guys or not.
I'm trying to catch the 'after entry is saved' event, using the following code in my custom module's init() function (The module's code is generated by pluginfactory.io):
Event::on(
    \craft\services\Elements::class,
    \craft\services\Elements::EVENT_AFTER_SAVE_ELEMENT,
    function (\craft\events\ElementEvent $event) {
        $element = $event->element;
        if($element instanceof \craft\elements\Entry) {
            // Craft::info('Entry saved: ' . $element->title, __METHOD__);
        }
    }
);

It seems to work by testing on saving an entry in the CP, but the weird thing is this event seems to be triggered twice according to the log:
2019-08-16 12:21:52 [-][1][-][info][modules\testmodule\{closure}] Entry saved: Document translation
2019-08-16 12:21:52 [-][1][-][info][modules\testmodule\{closure}] Entry saved: Document translation
2019-08-16 12:21:52 [-][1][-][info][application] $_GET = [
    'p' => 'admin/entries/pages/234-document-translation'
]

I also tried Andrew's answer in this post: https://craftcms.stackexchange.com/a/26815/7136, but same thing happened.
Event::on(
    \craft\elements\Entry::class,
    \craft\elements\Entry::EVENT_AFTER_SAVE,
    function (\craft\events\ModelEvent $event) {
        Craft::debug(
            '\craft\elements\Entry::EVENT_AFTER_SAVE',
            __METHOD__
        );
    }
);

I certainly don't want my custom code to be executed twice. Is this a bug or an expected behavior?
Craft version: 3.2.10

**Tags:** craft3, events

---

## 2 answers

### Answer by username_0 on 2019-08-19. Score: 7 | Accepted answer

After using Andrew's debugging tip, I found out one event was triggered by saving the element itself, and the other was triggered by saving the revision of the element. So I modified my event listener to be like the following, and it solved the double-up issue:
Event::on(
    \craft\services\Elements::class,
    \craft\services\Elements::EVENT_AFTER_SAVE_ELEMENT,
    function (\craft\events\ElementEvent $event) {
        $element = $event->element;
        if(
            $element instanceof \craft\elements\Entry // is entry
            && $element->getSection()->handle == 'pages' // is in 'pages' section
            && !$element->getIsRevision() // is not revision
            && !$element->getIsDraft() // is not draft
            // && !$element->propagating // not during propagating (avoid batch propagating)
            // && !$element->resaving // not during resaving (avoid batch resaving)
        ) {
            // --------------- My Stuff -------------- //
            // $entry is the $element
            // $isNew = $event->isNew
            // ...
        }
    }
);

Depending on what you are trying to do in the event handler, you might want to toggle some if conditions. For example, you might want to avoid the same handler executed hundreds of times during a batch of re-saving action which is triggered when a section's setting is updated and Craft automatically re-saves all the entries under the section. In this case, you might consider having a separate EVENT_AFTER_RESAVE_ELEMENTS event handler.

> **Comments:**
> **username_1**: Nicely done tracking it down! If you're using Craft 3.2, there's a helper: `ElementHelper::isDraftOrRevision($element)`  
> **username_0**: @andrew.welch ahh, good to know. Thanks!  

---

### Answer by username_1 on 2019-08-16. Score: 6

You can find out what the stack trace is (who is calling you) by putting something like this in your anonymous function:
                try {
                    throw new \Exception();
                } catch (\Exception $e) {
                    Craft::debug(
                        'EVENT_AFTER_SAVE_ELEMENT '.$e->getTraceAsString(),
                        __METHOD__
                    );
                }

Then search on EVENT_AFTER_SAVE_ELEMENT in your web.log

> **Comments:**
> **username_0**: Great tip! Thanks, Andrew!  

---

