Jump to content
LostKobrakai

WireCache and JSON data quirks

Recommended Posts

WireCache is a really nice way to quickly cache data to the database, but when working with json data there are some quirks. Imagine the following examples:

$data = $cache->get('my-key', WireCache::expireHourly);
if(!$data){
	$data = […]
	$cache->save('my-key', $data, WireCache::expireHourly);
}

// API response
$response = json_decode($data);
$image = $response->data[0]->image;

// or 
$html = "<div data-json='$data'></div>";

Both should work from the quick look. Both will fail as soon as the cache kicks in. This is because the implementation of WireCache tries to be smart and does automatically decode data, which is detected to be json. But it doesn't just decode it like in my example, but rather uses json_decode()'s second parameter to decode the json as associative array(s) instead of stdobject(s).

If you prefer the object syntay to traverse your json data or you really want to store raw json, then I've got two hooks for you, which do prevent the automatic json detection of WireCache, so you can work with the stringified json as you need to. Just replace the get() and save() calls in the example with getRaw() and saveRaw().

$wire->addHook('WireCache::saveRaw', function(HookEvent $event){
	$args = $event->arguments();
	$args[1] = '::RAW::' . $args[1];
	return $event->return = call_user_func_array([$event->object, 'save'], $args);
});

$wire->addHook('WireCache::getRaw', function(HookEvent $event){
	$args = $event->arguments();
	return $event->return = str_replace('::RAW::', '', call_user_func_array([$event->object, 'get'], $args));
});
  • Like 11

Share this post


Link to post
Share on other sites

Or get + set combined:

$data = $cache->get('my-key', WireCache::expireHourly, function() {

	return []; // return array (for example), if returns absolute false, won't get cached.
});

Share this post


Link to post
Share on other sites

I don't like the one line syntax, because I'd need to explicitly 'use' all variables declared somewhere else in the template, so they are available in the anonymous function. And secondly it's not possible to add the things I added above without recreating the whole get() function in a hook.

Share this post


Link to post
Share on other sites

@LostKobrakai,

  Thank you for taking the time to point this out. I have not yet done any coding involving Wire Cache, I've just started playing around with Hanna codes :lol:  , but I am definitely going to be saving this link for future reference. Thanks again.

Share this post


Link to post
Share on other sites

Thanks for this @LostKobrakai!

I just came across this very problem, thankfully I found this thread. Took me a while to understand how your solution works, certainly a creative solution to just add a string to make the cached value invalid JSON 😄

I modified your code slightly:

const RAW_PREFIX = '::RAW::';

$wire->addHook('WireCache::saveRaw', function (HookEvent $event) {
    $args = $event->arguments();
    $args[1] = RAW_PREFIX . $args[1];
    return $event->return = call_user_func_array([$event->object, 'save'], $args);
});

$wire->addHook('WireCache::getRaw', function (HookEvent $event) {
    $args = $event->arguments();
    $cached_val = call_user_func_array([$event->object, 'get'], $args);
    return $event->return = $cached_val === null
        ? null
        : substr($cached_val, strlen(RAW_PREFIX));
});

I made two notable changes:

  • If the Cache API returns null (i.e. no cached value exists), getRaw will also return null instead of an empty string.
  • Use substr instead of str_replace, since it will be faster for long strings and it won't break anything in case the RAW_PREFIX (::HOOK::) appears anywhere inside the cached value (I'm a bit paranoid 😄
  • Like 1

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...