Skip to content

Commit

Permalink
Custom serializer support
Browse files Browse the repository at this point in the history
  • Loading branch information
Gerych1984 committed Mar 14, 2024
1 parent 642f32f commit 36cb676
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 6 deletions.
13 changes: 7 additions & 6 deletions src/DbCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,8 @@
use function is_string;
use function iterator_to_array;
use function random_int;
use function serialize;
use function strpbrk;
use function time;
use function unserialize;

/**
* DbCache stores cache data in a database table.
Expand All @@ -37,6 +35,7 @@ final class DbCache implements CacheInterface

private string $loggerMessageDelete = 'Unable to delete cache data: ';
private string $loggerMessageUpdate = 'Unable to update cache data: ';
private SerializerInterface $serializer;

/**
* @param ConnectionInterface $db The database connection instance.
Expand All @@ -48,8 +47,10 @@ final class DbCache implements CacheInterface
public function __construct(
private ConnectionInterface $db,
private string $table = '{{%yii_cache}}',
public int $gcProbability = 100
public int $gcProbability = 100,
?SerializerInterface $serializer = null
) {
$this->serializer = $serializer ?? new PhpSerializer();
}

/**
Expand All @@ -75,7 +76,7 @@ public function get(string $key, mixed $default = null): mixed
/** @var bool|float|int|string|null $value */
$value = $this->getData($key, ['data'], 'scalar');

return $value === false ? $default : unserialize((string) $value);
return $value === false ? $default : $this->serializer->restore((string) $value);
}

/**
Expand Down Expand Up @@ -142,7 +143,7 @@ public function getMultiple(iterable $keys, mixed $default = null): iterable
}

/** @psalm-var string */
$values[$value['id']] = unserialize((string) $value['data']);
$values[$value['id']] = $this->serializer->restore((string) $value['data']);
}

/** @psalm-var iterable<string,mixed> */
Expand Down Expand Up @@ -289,7 +290,7 @@ private function deleteData(array|string|bool $id): bool
private function buildDataRow(string $id, ?int $ttl, mixed $value, bool $associative): array
{
$expire = $this->isInfinityTtl($ttl) ? null : ((int) $ttl + time());
$data = new Param(serialize($value), PDO::PARAM_LOB);
$data = new Param($this->serializer->serialize($value), PDO::PARAM_LOB);

if ($associative) {
return ['id' => $id, 'expire' => $expire, 'data' => $data];
Expand Down
27 changes: 27 additions & 0 deletions src/PhpSerializer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Cache\Db;

use function serialize;
use function unserialize;

final class PhpSerializer implements SerializerInterface
{
public function serialize(mixed $value): string
{
return serialize($value);
}

/**
* @param string $value
* @return mixed
*
* @psalm-suppress MixedArgumentTypeCoercion
*/
public function restore(string $value): mixed
{
return unserialize($value);
}
}
12 changes: 12 additions & 0 deletions src/SerializerInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Cache\Db;

interface SerializerInterface
{
public function serialize(mixed $value): string;

public function restore(string $value): mixed;
}
64 changes: 64 additions & 0 deletions tests/PhpSerializerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Cache\Db\Tests;

use PHPUnit\Framework\TestCase;
use stdClass;
use Yiisoft\Cache\Db\PhpSerializer;

use function pi;

use const PHP_INT_MAX;

final class PhpSerializerTest extends TestCase
{
public static function serializeDataProvider(): array
{
$object = new stdClass();
$object->foo = 'bar';
$object->bar = 'foo';

return [
[
true,
],
[
PHP_INT_MAX,
],
[
pi(),
],
[
'string',
],
[
[
'key' => 'value',
'foo' => 'bar',
],
],
[
$object,
],
];
}

/**
* @dataProvider serializeDataProvider
* @param mixed $data
* @return void
*/
public function testSerialize(mixed $data): void
{
$serializer = new PhpSerializer();
$result = $serializer->serialize($data);

if (is_object($data)) {
self::assertEquals($data, $serializer->restore($result));
} else {
self::assertSame($data, $serializer->restore($result));
}
}
}

0 comments on commit 36cb676

Please sign in to comment.