matthiasmullie / scrapbook

PHP cache library, with adapters for e.g. Memcached, Redis, Couchbase, APC(u), SQL and additional capabilities (e.g. transactions, stampede protection) built on top.

Home Page:https://www.scrapbook.cash

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Invalid key: test:string. Contains (a) character(s) reserved for future extension:

KarelWintersky opened this issue · comments

$backend = new \Redis();
$backend->connect('localhost');
$backend->select(1);

$cache = new \MatthiasMullie\Scrapbook\Adapters\Redis( $backend );
$pool = new \MatthiasMullie\Scrapbook\Psr6\Pool($cache);

$item = $pool->getItem('test:string');

var_dump($item->get());

return:

PHP Fatal error:  Uncaught MatthiasMullie\Scrapbook\Psr6\InvalidArgumentException: Invalid key: test:string. Contains (a) character(s) reserved for future extension: {}()/\@: in .../vendor/matthiasmullie/scrapbook/src/Psr6/Pool.php:247
Stack trace:
#0 .../vendor/matthiasmullie/scrapbook/src/Psr6/Pool.php(58): MatthiasMullie\Scrapbook\Psr6\Pool->assertValidKey()
#1 .../test_redis_scrapbook.php(14): MatthiasMullie\Scrapbook\Psr6\Pool->getItem()
#2 {main} thrown in .../vendor/matthiasmullie/scrapbook/src/Psr6/Pool.php on line 247

but Redis allowed this key:

root@quartz:/etc/redis# redis-cli --version
redis-cli 6.2.6

root@quartz:/etc/redis# redis-cli

127.0.0.1:6379> set test:string 'foobar'
OK
127.0.0.1:6379> get test:string
"foobar"
127.0.0.1:6379> 

WTF?

See also: https://redis.io/topics/data-types-intro#redis-keys

Redis keys are binary safe, this means that you can use any binary sequence as a key, from a string like "foo" to the content of a JPEG file. The empty string is also a valid key.

A few other rules about keys:

...
Very short keys are often not a good idea. There is little point in writing "u1000flw" as a key if you can instead write "user:1000:followers". The latter is more readable and the added space is minor compared to the space used by the key object itself and the value object. While short keys will obviously consume a bit less memory, your job is to find the right balance.
Try to stick with a schema. For instance "object-type:id" is a good idea, as in "user:1000". Dots or dashes are often used for multi-word fields, as in "comment:1234:reply.to" or "comment:1234:reply-to".

: character in a key is allowed by \MatthiasMullie\Scrapbook\Adapters\Redis if used directly, but is reserved if used via a PSR-6 interface (see in https://www.php-fig.org/psr/psr-6/ the definition of Key).

If you don't wrap your \MatthiasMullie\Scrapbook\Adapters\Redis instance with a PSR interface adapter, those keys will be accepted:

        $backend = new \Redis();
        $backend->connect('localhost');
        $backend->select(1);

        $cache = new \MatthiasMullie\Scrapbook\Adapters\Redis( $backend );
        $cache->set('test:string', 'oh hi');

        var_dump($cache->get('test:string')); // this works

        $pool = new \MatthiasMullie\Scrapbook\Psr6\Pool($cache);
        var_dump($pool->getItem('test:string')); // this throws \MatthiasMullie\Scrapbook\Psr6\InvalidArgumentException
$cache = new \MatthiasMullie\Scrapbook\Adapters\Redis( $backend );

How check, is value with key xxx present? Can't find method at class autocompletion methods :(

You can test presence of a cache key by checking that $cache->get( 'xxx' ) !== false