1

I have implemented the Symfony Cache Component using RedisAdapter. Now we like to use a colon as separator in cache keys (e.g. some:cache:key:25). Just like Redis recommends.

I get an Exception saying "contains reserved characters {}()/\@: etc.". This is explained in Symfony Documentation

(https://symfony.com/doc/3.4/components/cache/cache_items.html) that those are reserved characters in PSR-6.

I like to know if there is a way around that? Because i am busy refactoring cache logic using Symfony Cache Component. But keys are already defined, so i am not able to change them without breaking conventions.

Rahul Agarwal
  • 4,034
  • 7
  • 27
  • 51
fredtro
  • 63
  • 7

2 Answers2

2

As you noted : is a reserved character in the PSR-6 cache standard, which Symfony's cache component builds on.

If you want to keep them in your code, you could write an adapter that takes your keys and replaces the : with something else before passing it to the regular cache.

So for example you could write an adapter that looks something like this:

class MyCacheAdapter implements AdapterInterface
{
    private $decoratedAdapter;

    public function __construct(AdapterInterface $adapter)
    {
        $this->decoratedAdapter = $adapter;
    }

    public function getItem($key): CacheItemInterface
    {
        $key = str_replace(':', '.', $key);

        return $this->decoratedAdapter->getItem($key);
    }

    ...
}

For all other methods you can just proxy the call to the decorated service and return the result. It's a bit annoying to write, but the interface demands it.

In your service configuration you can configure it like this:

services:
    App\Cache\MyCacheAdapter:
        decorates: 'Symfony\Component\Cache\Adapter\RedisAdapter'
        arguments:
            $adapter: '@app.cache.adapter.redis'

This configuration is only a rough outline both argument and the class names might have to be adjusted. In any case with this service decoration your adapter wraps around the original redis adapter and then when you configure it to be used by the cache component it should work fine, that your existing keys like some:cache:key25 will be converted to some.cache.key25 before they are passed into the cache component, so before the error message happens.

dbrumann
  • 16,803
  • 2
  • 42
  • 58
  • i like that approach. thanks a lot. the thing is, people at my place like to have colon in the keys, so that redis clients work correctly (e.g. list redis values as directory folder). but perhaps i have to discuss further with my team. – fredtro Oct 21 '18 at 19:08
  • 1
    In that case, if you want to keep the colon in redis as well, you have to write your own adapter that does not extend the AbstractAdapter and that ignores the validation check. If you look at the AbstractAdapter you should see where the exception is thrown and then replace the closures used to perform the check. It might be that other places in the cache component need adjustment as well for that. – dbrumann Oct 22 '18 at 14:47
0

In addition to the @dbrumann reply: semicolon is not the only character that is reserved. ItemInterface::RESERVED_CHARACTERS has a full list. Other approaches to make cache key safe:

$cacheKey = str_replace(str_split(ItemInterface::RESERVED_CHARACTERS), '-', $str);

or simpler

$cacheKey = hash('crc32b', $str);
Eugene Kaurov
  • 2,356
  • 28
  • 39