diff --git a/README.md b/README.md index c016951..b14dcdf 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,7 @@ function getCategoriesCount() ``` -### Simplified interface +### Extended interface ### Using cache tags diff --git a/src/CacheItemContract.php b/src/CacheItemContract.php index 76bb956..2cb7bf6 100644 --- a/src/CacheItemContract.php +++ b/src/CacheItemContract.php @@ -5,6 +5,12 @@ use Psr\Cache\CacheItemInterface; /** + * CacheItemContract extends {@see \Psr\Cache\CacheItemInterface}, adding extra features. + * + * It allows managing cache dependencies. + * + * @see \yii1tech\psr\cache\CacheItemPoolContract + * * @author Paul Klimov * @since 1.0 */ diff --git a/src/CacheItemPool.php b/src/CacheItemPool.php index 9c62a74..7472533 100644 --- a/src/CacheItemPool.php +++ b/src/CacheItemPool.php @@ -4,7 +4,6 @@ use CApplicationComponent; use Psr\Cache\CacheItemInterface; -use Psr\Cache\CacheItemPoolInterface; use Yii; /** @@ -34,7 +33,7 @@ * @author Paul Klimov * @since 1.0 */ -class CacheItemPool extends CApplicationComponent implements CacheItemPoolInterface +class CacheItemPool extends CApplicationComponent implements CacheItemPoolContract { /** * @var bool whether to automatically commit all deferred items on object destruction. @@ -230,4 +229,24 @@ public function commit(): bool return $result; } + + /** + * {@inheritdoc} + */ + public function get(string $key, callable $callback) + { + $item = $this->getItem($key); + + if ($item->isHit()) { + return $item->get(); + } + + $value = call_user_func($callback, $item); + + $item->set($value); + + $this->save($item); + + return $value; + } } \ No newline at end of file diff --git a/src/CacheItemPoolContract.php b/src/CacheItemPoolContract.php new file mode 100644 index 0000000..7532b65 --- /dev/null +++ b/src/CacheItemPoolContract.php @@ -0,0 +1,54 @@ + + * @since 1.0 + */ +interface CacheItemPoolContract extends CacheItemPoolInterface +{ + /** + * {@inheritdoc} + * + * @return \yii1tech\psr\cache\CacheItemContract the corresponding Cache Item. + */ + public function getItem($key); + + /** + * {@inheritdoc} + * + * @return \Traversable|array collection of Cache Items keyed by the cache keys of each item. + */ + public function getItems(array $keys = []); + + /** + * Fetches a value from the pool or computes it via given callback if not found. + * Usage example: + * + * ```php + * $value = $pool->get('example-cache-key', function (CacheItemContract $item) { + * $item->expiresAfter(3600); + * + * // ... + * + * return $computedValue; // heavy computations result + * }); + * ``` + * + * @template T + * + * @param string $key the key of the item to retrieve from the cache. + * @param (callable(CacheItemContract,bool):T)|(callable(CacheItemContract,bool):T) $callback callback, which computes value to be cached. + * @return T cached value or callback result. + */ + public function get(string $key, callable $callback); + + //public function invalidateTags(array $tags); +} \ No newline at end of file diff --git a/tests/CacheItemPoolTest.php b/tests/CacheItemPoolTest.php index ec6d574..6e9c253 100644 --- a/tests/CacheItemPoolTest.php +++ b/tests/CacheItemPoolTest.php @@ -5,6 +5,7 @@ use CDummyCache; use DateInterval; use ICache; +use yii1tech\psr\cache\CacheItemContract; use yii1tech\psr\cache\CacheItemPool; class CacheItemPoolTest extends TestCase @@ -232,4 +233,35 @@ public function testSaveWithDependency(): void $item = $pool->getItem($key); $this->assertFalse($item->isHit()); } + + /** + * @depends testSave + */ + public function testGetCallback(): void + { + $pool = new CacheItemPool(); + + $key = 'test'; + + $value = $pool->get($key, function (CacheItemContract $item) { + $item->expiresAfter(DateInterval::createFromDateString('1 hour')); + + return 'test-value'; + }); + + $this->assertSame('test-value', $value); + + $item = $pool->getItem($key); + $this->assertTrue($item->isHit()); + $this->assertSame('test-value', $item->get()); + + $value = $pool->get($key, function (CacheItemContract $item) { + $item->expiresAfter(DateInterval::createFromDateString('1 hour')); + + return 'new-value'; + }); + + $this->assertSame('test-value', $value); + $this->assertSame('test-value', $pool->getItem($key)->get()); + } } \ No newline at end of file