Hi! Long time user of Kirby – and this forum – here. Thank you for Kirby; it’s awesome!
I’m considering building a local caching system for speeding up functions that either take a while to compute or that are called very often.
Am I on the right track here, or perhaps there are better or more elegant solutions?
Let’s say that I have a function like this (in a Page object):
public function complicatedCalculation()
{
// Return value.
return “Something that takes some time to compute.”
}
I would like to (1) use a cached value if it exists (and if it does not exist, create it), and (2) manually refresh the cached value, via a hook, only when necessary.
So far, this is what I got.
In config.php, I have added this:
'cache' => [
'cachedvalues' => true
]
Here is what the above function could look like with caching. The idea is to use the Page object and the name of the function as a unique key for the cached value:
public function complicatedCalculation($useCache = true)
{
// Use cache if possible.
if ($useCache) return getCachedValue($this, 'complicatedCalculation');
// Return value.
return “Something that takes some time to compute.”
}
Here is the main function, getCachedValue, to achieve this:
function getCachedValue($page, $key, $refreshCache = false) {
// Get cache.
$cache = kirby()->cache('cachedvalues');
// Get cache key.
$cacheKey = $page->id() . '/' . $key;
// Get cached value, if it exists.
$cachedValue = $cache->get($cacheKey);
// Update the cached value if the value is not set or we are manually refreshing it.
if ($cachedValue === null || $refreshCache) {
// Get the value by calling the function named $key for the $page object.
$cachedValue = $page->$key(useCache: false);
// Set cache.
$cache->set($cacheKey, $cachedValue);
}
// Return cached value.
return $cachedValue;
}
Then, in the appropriate hooks, I can manually update the values exactly when I need to. For example like this:
'page.update:after' => function ($newPage, $oldPage) {
getCachedValue($newPage, 'complicatedCalculation', refreshCache: true);
}
Am I doing this right, or am I confused? Are there obvious improvements or things I’m missing? So far, it seems to work great, but I suspect that there are better ways to achieve what I want. Suggestions or ideas?