[Cache] Support a custom serializer in the ApcuAdapter class

This commit is contained in:
Stefano Arlandini 2021-03-27 23:53:30 +01:00 committed by Fabien Potencier
parent b2e46a92a9
commit 1ef44ae7c6
3 changed files with 39 additions and 2 deletions

View File

@ -13,16 +13,19 @@ namespace Symfony\Component\Cache\Adapter;
use Symfony\Component\Cache\CacheItem; use Symfony\Component\Cache\CacheItem;
use Symfony\Component\Cache\Exception\CacheException; use Symfony\Component\Cache\Exception\CacheException;
use Symfony\Component\Cache\Marshaller\MarshallerInterface;
/** /**
* @author Nicolas Grekas <p@tchwork.com> * @author Nicolas Grekas <p@tchwork.com>
*/ */
class ApcuAdapter extends AbstractAdapter class ApcuAdapter extends AbstractAdapter
{ {
private $marshaller;
/** /**
* @throws CacheException if APCu is not enabled * @throws CacheException if APCu is not enabled
*/ */
public function __construct(string $namespace = '', int $defaultLifetime = 0, string $version = null) public function __construct(string $namespace = '', int $defaultLifetime = 0, string $version = null, ?MarshallerInterface $marshaller = null)
{ {
if (!static::isSupported()) { if (!static::isSupported()) {
throw new CacheException('APCu is not enabled.'); throw new CacheException('APCu is not enabled.');
@ -40,6 +43,8 @@ class ApcuAdapter extends AbstractAdapter
apcu_add($version.'@'.$namespace, null); apcu_add($version.'@'.$namespace, null);
} }
} }
$this->marshaller = $marshaller;
} }
public static function isSupported() public static function isSupported()
@ -57,7 +62,7 @@ class ApcuAdapter extends AbstractAdapter
$values = []; $values = [];
foreach (apcu_fetch($ids, $ok) ?: [] as $k => $v) { foreach (apcu_fetch($ids, $ok) ?: [] as $k => $v) {
if (null !== $v || $ok) { if (null !== $v || $ok) {
$values[$k] = $v; $values[$k] = null !== $this->marshaller ? $this->marshaller->unmarshall($v) : $v;
} }
} }
@ -104,6 +109,10 @@ class ApcuAdapter extends AbstractAdapter
*/ */
protected function doSave(array $values, int $lifetime) protected function doSave(array $values, int $lifetime)
{ {
if (null !== $this->marshaller && (!$values = $this->marshaller->marshall($values, $failed))) {
return $failed;
}
try { try {
if (false === $failures = apcu_store($values, null, $lifetime)) { if (false === $failures = apcu_store($values, null, $lifetime)) {
$failures = $values; $failures = $values;

View File

@ -5,6 +5,7 @@ CHANGELOG
--- ---
* added support for connecting to Redis Sentinel clusters when using the Redis PHP extension * added support for connecting to Redis Sentinel clusters when using the Redis PHP extension
* add support for a custom serializer to the `ApcuAdapter` class
5.2.0 5.2.0
----- -----

View File

@ -14,6 +14,7 @@ namespace Symfony\Component\Cache\Tests\Adapter;
use Psr\Cache\CacheItemPoolInterface; use Psr\Cache\CacheItemPoolInterface;
use Psr\Log\NullLogger; use Psr\Log\NullLogger;
use Symfony\Component\Cache\Adapter\ApcuAdapter; use Symfony\Component\Cache\Adapter\ApcuAdapter;
use Symfony\Component\Cache\Marshaller\MarshallerInterface;
class ApcuAdapterTest extends AdapterTestCase class ApcuAdapterTest extends AdapterTestCase
{ {
@ -122,4 +123,30 @@ class ApcuAdapterTest extends AdapterTestCase
restore_error_handler(); restore_error_handler();
} }
} }
public function testCacheItemValueRunsThroughMarshaller()
{
$namespace = str_replace('\\', '.', static::class);
$marshaller = $this->createMock(MarshallerInterface::class);
$marshaller->expects($this->once())
->method('marshall')
->with([$namespace.':foo' => 'bar'])
->willReturn([$namespace.':foo' => 'bar_serialized']);
$marshaller->expects($this->once())
->method('unmarshall')
->with('bar_serialized')
->willReturn('bar');
$pool = new ApcuAdapter($namespace, 0, 'p1', $marshaller);
$item = $pool->getItem('foo');
$this->assertFalse($item->isHit());
$this->assertTrue($pool->save($item->set('bar')));
$item = $pool->getItem('foo');
$this->assertTrue($item->isHit());
$this->assertSame('bar', $item->get());
}
} }