Jump to content

Cache API: Clear cache on template save AND date change


felix
 Share

Recommended Posts

Hey folks,

I'm trying to cache a lot of event & news entrys that get loaded on several pages. There are two conditions that - when met - require the cache to be invalidated:

- A page with the Template "news-detail" is saved

- The Cachefile is older than "Today at midnight"

The first condition is easy (see code below). What about the second?

Is there a way to combine both conditions (template change and caching time) using the cache api? Will I have to use cron/lazycron to purge the cache every 24hrs?

	private function getCachedNews($parentId, \PageArray $filter = null) {

		$template = wire('templates')->get(self::NEWS_TEMPLATE);
		$cache = wire('cache');
		$addedFilters = '';
		if(!is_null($filter)) $addedFilters = '_' . $filter->implode('', 'name');

		$newsSelector = 'news_' . $parentId . $addedFilters;

		$news = $cache->get($newsSelector, $template, function($pages) {
			// here be newslogic dragons [...]
			return $retVal;
		}); 	

		return $news;

	}
Link to comment
Share on other sites

I think cache purging will be done automatically, so no need to care about that. To invalidate by save and today at midnight I'd just add the following to the cache key: 

$key = "news_";
// You key properties
$key .= $page->modified . "_";
$key .= date("Y-m-d");

$page->modified will not match if a page got saved since the last cache and date won't match if – guess what – the date has changed and therefore today at midnight has passed.

  • Like 1
Link to comment
Share on other sites

I had this kind of issue with cached navigation (one for desktop, one for mobile = mmenu), and wanted to make sure the database cache is removed as soon i save one of the pages displayed in the navigation. I came up with a module that hooks in to page save.

It removes the necessary cache items asfollow:

- when pages with template settings_socialmedia or settings_textblocks are saved it removes the main.footer cache entry

- when pages with template list_agenda or item_agenda are saved it removes the block.agenda cache entry

- when any of the pages in $navigationPages are saved it removes both the man.navbar and main.mmenu cache entries

<?php

/**
 * ProcessWire Save Actions
 *
 * Actions to be run on page save
 *
 * @ 2015 Raymond Geerts
 *
 * ProcessWire 2.x
 * Copyright (C) 2014 by Ryan Cramer
 * Licensed under GNU/GPL v2, see LICENSE.TXT
 *
 * http://processwire.com
 *
 */

class SaveActions extends WireData implements Module {

    /**
     * Return information about this module (required)
     *
     */
    public static function getModuleInfo() {
        return array(
            'title' => 'Save Actions',
            'summary' => 'Actions to be run on page save',
            'version' => 1,
            'autoload' => "template=admin",
            'singular' => true,
            'author' => 'Raymond Geerts',
            'icon' => 'floppy-o'
        );
    }
    public function init() {
        $this->pages->addHookAfter('save', $this, 'actionsAfterSave');
    }
    public function actionsAfterSave($event) {
        $page = $event->arguments[0];

        if ($page->template == 'settings_socialmedia' ||
            $page->template == 'settings_textblocks'
        ) {
            $this->cache->delete("main.footer");
            $this->message("Cleaned WireCache for front-end footer HTML");
        }
        elseif ($page->template == 'list_agenda' ||
                $page->template == 'item_agenda'
        ) {
            $this->cache->delete("block.agenda");
            $this->message("Cleaned WireCache for front-end agenda block HTML");
        }
        else {
            $homepage = $this->pages->get('/');
            $navigationPages = $homepage->and($homepage->children);

            foreach($homepage->and($homepage->children) as $item) {
                if ($item->template->altFilename == "clickthrough" &&
                    $item->hasChildren()
                ) {
                    $navigationPages->append($item->children);
                }
            }

            if ($navigationPages->has($page)) {
                $this->cache->delete("main.navbar");
                $this->cache->delete("main.mmenu");
                $this->message("Cleaned WireCache for front-end navbar HTML");
            }
        }
    }
}

It saved some page-loading time when caching navigations. Because they are displayed on every page, its a smart thing to do.

A trick to make the current page (and parents) have a selected / active class i did the following:

in the head of the _main.php

<script>
var globalJS = <?php

$globalJS = array();
$globalJS['parents'] = $page->parents()->remove($homepage)->append($page)->each('id');

echo json_encode($globalJS, JSON_FORCE_OBJECT);

?>
</script>

in the navigation i put the page ID in each <li> item like this:

echo "<li id='navbar-pageID-{$item->id} role='presentation'>";

(and in mmenu as follow:)

echo "<li id='mmenu-pageID-{$item->id}'>";

In my main.js file i have the following:

(function() {
  // set navigation menu items active
  $.each(globalJS.parents, function(key, value){
    $('#navbar-pageID-'+value).addClass('active');
    $('#mmenu-pageID-'+value).addClass('current');
  });
}());
  • Like 4
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...