Note the non-serialization error in CakePHP via Redis

Update:

According to the accepted answer below, I tested a negative number:

$negativeInt = -1;
Cache::write('my-test-count', $negativeInt, 'short');
$readVal = Cache::read('my-test-count', 'short');
debug($readVal);
exit;

The unseralize error is reproduced sequentially when trying to read any negative number. This is now an accepted error, which, I believe, will be resolved at 2.8.1


The original question:

I keep getting this error, but I can’t understand why and even how to continue troubleshooting.

The line that throws an error should only go if it Cache::read()returns false. But this line would throw a non-serialization error if I didn't put @ in front of it.

: Redis Noterialize? "", , , ::read. , (int) (. ), , , .

(8): unserialize(): 0 2 [APP/Vendor/pear-pear.cakephp.org/CakePHP/Cake/Cache//RedisEngine.php, 136]

:

> unserialize - [internal], line ??
> RedisEngine::read() - APP/Vendor/pear-pear.cakephp.org/CakePHP/Cake/Cache/Engine/RedisEngine.php, line 136
> Cache::read() - APP/Vendor/pear-pear.cakephp.org/CakePHP/Cake/Cache/Cache.php, line 358
> Cache::remember() - APP/Vendor/pear-pear.cakephp.org/CakePHP/Cake/Cache/Cache.php, line 567
> Item::getCount() - APP/Model/Item.php, line 812

, :

public function getCount($id) {
    $model = $this;

    // here is where the Cache::read() and debug are in the update below

    return Cache::remember('item' . $id. '_count', function() use ($model, $id) {
        $count = $model->find('count', array(
            'conditions' => array(
                $model->alias . '.status' => 1,
                $model->alias . '.id' => $id
            )
        ));
        return ($count === false) ? 0 : (int)$count;
    }, 'my_counts'); // THIS IS LINE 812
}

public function decrementCount($id, $offset = 1) {
    if(empty($id)) return false;
    $count = @Cache::read('item' . $id . '_count', 'my_counts');
    if($count === false) {
        $this->getCount($id);
    } else {
        Cache::decrement('item' . $id . '_count', $offset, 'my_counts');
    }
}

public function incrementCount($id, $offset = 1) {
    if(empty($id)) return false;
    $count = @Cache::read('item' . $id. '_count', 'my_counts');
    if($count === false) {
        $this->getCount($id);
    } else {
        Cache::increment('item' . $id. '_count', $offset, 'my_counts');
    }
}

UPDATE:

( 1-20 ). Cache::remember(...:

$toReturn = Cache::read('item' . $id. '_count', 'my_counts');
debug($toReturn);

:

  • debug: (int) 0
  • debug: (int) 0
  • (8): unserialize(): ... ( : )
  • debug: false
  • (8): unserialize(): ... ( Cache::
  • debug: (int) 0
  • (8): unserialize(): ... ( : )
  • debug: false
  • (8): unserialize(): ... ( Cache::
  • 0
  • 3
  • 1
  • 1 ...
+4
3

, . , .

, int(-1). RedisEngine , . int(-1) serialize().

public function write($key, $value, $duration) {
    if (!is_int($value)) {
        $value = serialize($value);
    }
    ...
}

. Redis , , Redis int(-1) string(-1). ctype_digit("-1") false, string(-1) .

public function read($key) {
    $value = $this->_Redis->get($key);
    if (ctype_digit($value)) { // ctype_digit("-1") === false
        $value = (int)$value;
    }
    if ($value !== false && is_string($value)) { // is_string("-1") === true
        $value = unserialize($value);
    }
    ...
}

, " (8): unserialize(): 0 2 ". string(-1) 2 .

github, int(-1), .

, Cache::decrement(). int(-1). Cache::write(), . :

$count = Cache::read('item' . $id. '_count', 'my_counts');
if ($count === false || 0 > $count - $offset) {
    $this->getCount($id);
} else {
    Cache::write('item' . $id. '_count', $count - $offset, 'my_counts');
}

, /.

, , .

+2

:

return ($count === false) ? 0 : (int)$count;

:

/.

Cache:: - :

$key = 'key';
$value = 10;
$serialized = serialize($value); // $serialized = 'i:10;'
$redis->set($key, $serialized);

Cache:: read - :

$key = 'key';
$serialized = $redis->get($key); // $serialized = 'i:10;'
$value = unserialize($serialized); // $value = (int) 10
return $value;

Cache:: - :

$key = 'key';
$count = 1;
$redis->decrby($key, $count); // Error, decrby expects plain value, "10", not "i:10;" ( http://redis.io/commands/decrby )

, , redis, :

$key = 'key';
$serialized = $redis->get($key); // $serialized = '10'
$value = unserialize($serialized); // error, cannot unserialize '10'

EDIT: : https://github.com/cakephp/cakephp/blob/master/src/Cache/Engine/RedisEngine.php

, Cake :

    if (!is_int($value)) {
        $value = serialize($value);
    }

, , , , - , (int).

0

Just remove the third parameter, it should work

return Cache::remember('item' . $id. '_count', function() use ($model, $id) {
    $count = $model->find('count', array(
        'conditions' => array(
            $model->alias . '.status' => 1,
            $model->alias . '.id' => $id
        )
    ));
    return ($count === false) ? 0 : (int)$count;
});
-1
source

Source: https://habr.com/ru/post/1625419/


All Articles