<p>I have a module that sends an email whenever a specific entry field is updated. Everything is working fine except that the field is being passed to the dirtyFields array even if it has not been updated causing the email to be sent when not needed.</p>
<p>Here is how the code works, I have an event (EVENT_AFTER_SAVE) being called when the entry is being saved, I check the type of the entry being saved, and if it is the correct one I do a subsequent check to see what fields changed for the entry, if the field needed has changed then it should send the email.</p>
<p>Here is the function that the event triggers:</p>
<pre><code>function (ModelEvent $event) {
    $entry = $event-&gt;sender;

    if (ElementHelper::isDraftOrRevision($entry)) {
        return;
    }

    if ($entry-&gt;type == 'store') {
        $dirtyFields = $entry-&gt;getDirtyFields();

        $this::$instance-&gt;sendEntryNotification($entry);

        foreach ($dirtyFields as $field) {
            if ($field == 'storeStatusV2') {
                $this::$instance-&gt;sendEntryNotification($entry);
            }
        }
    }
}
</code></pre>
<p>After doing some testing I realized that dirtyFields is returning all the fields inside the entry instead of the ones that have changed. What is the reason for this ?</p>

CC BY-SA 4.0
2021-11-09T21:29:19.230Z
I believe any time the `setFieldValue()` method is called, it flags the field as "dirty," even if the _values_ are the same. Any form that POSTs all of an Elements fields would result in the scenario you're describing, even if the values weren't “modified” from our perspective. To my knowledge, the only way to detect an actual change would be to re-load the Element out of the database _prior_ to it being saved (in `EVENT_BEFORE_SAVE`), memoize it somewhere, then in your `EVENT_AFTER_SAVE` handler, normalize + compare the values directly.
August Miller
CC BY-SA 4.0
2021-11-18T16:51:14.297Z
mm, that is a weird implementation since the documentation explains that dirty fields are the fields that have changed since they were loaded. I wonder if there is any other way to achieve this by using the same EVENT.
Jorge Sosa
CC BY-SA 4.0
2023-11-22T16:26:52.810Z
Experiencing the same issue with craft 4.
Masiorama
CC BY-SA 4.0
2023-11-22T16:39:12.770Z
Interesting info about the issue: https://github.com/craftcms/cms/issues/12967
Masiorama
<plugin-development><php><modules>
getDirtyFields returning more results than expected
# getDirtyFields returning more results than expected

(Asked by: username_0 on 2021-11-09)

I have a module that sends an email whenever a specific entry field is updated. Everything is working fine except that the field is being passed to the dirtyFields array even if it has not been updated causing the email to be sent when not needed.
Here is how the code works, I have an event (EVENT_AFTER_SAVE) being called when the entry is being saved, I check the type of the entry being saved, and if it is the correct one I do a subsequent check to see what fields changed for the entry, if the field needed has changed then it should send the email.
Here is the function that the event triggers:
function (ModelEvent $event) {
    $entry = $event->sender;

    if (ElementHelper::isDraftOrRevision($entry)) {
        return;
    }

    if ($entry->type == 'store') {
        $dirtyFields = $entry->getDirtyFields();

        $this::$instance->sendEntryNotification($entry);

        foreach ($dirtyFields as $field) {
            if ($field == 'storeStatusV2') {
                $this::$instance->sendEntryNotification($entry);
            }
        }
    }
}

After doing some testing I realized that dirtyFields is returning all the fields inside the entry instead of the ones that have changed. What is the reason for this ?

**Tags:** plugin-development, php, modules

> **Comments:**
> **username_1**: I believe any time the `setFieldValue()` method is called, it flags the field as "dirty," even if the _values_ are the same. Any form that POSTs all of an Elements fields would result in the scenario you're describing, even if the values weren't “modified” from our perspective. To my knowledge, the only way to detect an actual change would be to re-load the Element out of the database _prior_ to it being saved (in `EVENT_BEFORE_SAVE`), memoize it somewhere, then in your `EVENT_AFTER_SAVE` handler, normalize + compare the values directly.  
> **username_0**: mm, that is a weird implementation since the documentation explains that dirty fields are the fields that have changed since they were loaded. I wonder if there is any other way to achieve this by using the same EVENT.  
> **username_2**: Experiencing the same issue with craft 4.  
> **username_2**: Interesting info about the issue: https://github.com/craftcms/cms/issues/12967  

---

## 0 answers

