<p>You could technically do this with a lot of custom SQL, but it would be messy. I think your best bet would be to create a custom Date field on your categories called “Last Used”, and then to write a <a href="https://docs.craftcms.com/v3/extend/" rel="nofollow noreferrer">module</a> that keeps its value updated as entries are saved.</p>

<p>The default Craft 3 project comes with a <a href="https://github.com/craftcms/craft/blob/master/modules/Module.php" rel="nofollow noreferrer">module file</a> out of the box, so you can use that as a starting point.</p>

<p>First, add this to the top of the module file, after the <code>namespace</code> line:</p>

<pre class="lang-php prettyprint-override"><code>use Craft;
use craft\elements\Category;
use craft\elements\Entry;
use craft\events\ModelEvent;
use yii\base\Event;
</code></pre>

<p>Then in its <code>init()</code> method, add this after the <code>parent::init()</code> line:</p>

<pre class="lang-php prettyprint-override"><code>Event::on(Entry::class, Entry::EVENT_AFTER_SAVE, function(ModelEvent $event) {
    /** @var Entry $entry */
    $entry = $event-&gt;sender;

    if ($entry-&gt;enabled) {
        // Loop through the related categories
        foreach ($entry-&gt;myCategoriesField as $category) {
            /** @var Category $category */
            // Is this entry's post date more recent than the current Last Used value?
            if ($entry-&gt;postDate &gt; $category-&gt;lastUsed) {
                $category-&gt;setFieldValue('lastUsed', $entry-&gt;postDate);
                Craft::$app-&gt;elements-&gt;saveElement($category, false);
            }
        }
    }
});
</code></pre>

<p>You can get Craft to re-save all of your entries by re-saving each of your sections’ settings. (You don’t need to change anything.)</p>

<p>With that in place, you can start sorting by that custom field in your templates.</p>

<pre class="lang-twig prettyprint-override"><code>{% set categories = craft.categories()
    .group('myCategoryGroup')
    .lastUsed('not :empty:')
    .orderBy('lastUsed desc')
    .limit(4)
    .all() %}
</code></pre>

CC BY-SA 4.0
2018-10-22T21:28:10.733Z
Thanks Brandon. I'm on a client site that is currently using Craft 2. This will likely make me push to find the time to upgrade it. Unfortunately I have some unsupported plugins in the current install so won't be anytime soon. Many thanks for your time.
Adam Menczykowski
CC BY-SA 4.0
2018-10-22T21:31:40.653Z
@AdamMenczykowski Ah ok. You could technically pull something similar off in Craft 2 with a plugin, but there are a couple gotchas, like it’s much harder to update field values programmatically without messing other fields up.
Brandon Kelly
CC BY-SA 4.0
2018-10-23T13:59:37.027Z
Thanks, I'll probably work on getting the upgrade to v3 then try your suggestion.
Adam Menczykowski
CC BY-SA 4.0
2018-10-22T21:25:16.580Z
2018-10-22T21:25:16.580Z
Brandon Kelly
<p>I'm looking to show recent categories ordered by their associated entries' postDate.</p>

<p>Is this possible? </p>

<ul>
<li>I don't want to list the entries within the category</li>
<li>I simply want to list 4 categories that have recently updated related entries.</li>
<li>Entries from any section can be associated to my site's global categories.</li>
</ul>

<categories><relatedto><postdate>
Get categories ordered by the associated entries' postDate
# Get categories ordered by the associated entries' postDate

(Asked by: username_0 on 2018-10-22)

I'm looking to show recent categories ordered by their associated entries' postDate.

Is this possible?

* I don't want to list the entries within the category
* I simply want to list 4 categories that have recently updated related entries.
* Entries from any section can be associated to my site's global categories.

**Tags:** categories, relatedto, postdate

---

## 1 answers

### Answer by username_1 on 2018-10-22. Score: 2 | Accepted answer

You could technically do this with a lot of custom SQL, but it would be messy. I think your best bet would be to create a custom Date field on your categories called “Last Used”, and then to write a module that keeps its value updated as entries are saved.
The default Craft 3 project comes with a module file out of the box, so you can use that as a starting point.
First, add this to the top of the module file, after the namespace line:
use Craft;
use craft\elements\Category;
use craft\elements\Entry;
use craft\events\ModelEvent;
use yii\base\Event;

Then in its init() method, add this after the parent::init() line:
Event::on(Entry::class, Entry::EVENT_AFTER_SAVE, function(ModelEvent $event) {
    /** @var Entry $entry */
    $entry = $event->sender;

    if ($entry->enabled) {
        // Loop through the related categories
        foreach ($entry->myCategoriesField as $category) {
            /** @var Category $category */
            // Is this entry's post date more recent than the current Last Used value?
            if ($entry->postDate > $category->lastUsed) {
                $category->setFieldValue('lastUsed', $entry->postDate);
                Craft::$app->elements->saveElement($category, false);
            }
        }
    }
});

You can get Craft to re-save all of your entries by re-saving each of your sections’ settings. (You don’t need to change anything.)
With that in place, you can start sorting by that custom field in your templates.
{% set categories = craft.categories()
    .group('myCategoryGroup')
    .lastUsed('not :empty:')
    .orderBy('lastUsed desc')
    .limit(4)
    .all() %}

> **Comments:**
> **username_0**: Thanks Brandon. I'm on a client site that is currently using Craft 2. This will likely make me push to find the time to upgrade it. Unfortunately I have some unsupported plugins in the current install so won't be anytime soon. Many thanks for your time.  
> **username_1**: @AdamMenczykowski Ah ok. You could technically pull something similar off in Craft 2 with a plugin, but there are a couple gotchas, like it’s much harder to update field values programmatically without messing other fields up.  
> **username_0**: Thanks, I'll probably work on getting the upgrade to v3 then try your suggestion.  

---

