Skip to content

Commit 258d575

Browse files
committed
Adding ClassBoundCacheContract
ClassBoundCacheContract provides a developer friendly interface to fetch/set cache items related to a class automatically (using a unique getter that takes in parameter a resolver).
1 parent dfd0d2c commit 258d575

5 files changed

Lines changed: 131 additions & 2 deletions

File tree

README.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ $classBoundCache = new ClassBoundCache($fileBoundCache);
6060

6161
// Put the $myDataToCache object in cache.
6262
// If the FooBar class is modified, the cache item is purged.
63-
$classBoundCache->set('cache_key', $myDataToCache, FooBar::class);
63+
$classBoundCache->set('cache_key', $myDataToCache, new ReflectionClass(FooBar::class));
6464

6565
// Fetching data
6666
$myDataToCache = $classBoundCache->get('cache_key');
@@ -88,3 +88,28 @@ use TheCodingMachine\CacheUtils\ClassBoundMemoryAdapter;
8888

8989
$classBoundCache = new ClassBoundMemoryAdapter(new ClassBoundCache($psr16Cache));
9090
```
91+
92+
### Easier interface with cache contracts
93+
94+
You can even get an easier to use class bound cache using the `ClassBoundCacheContract`.
95+
96+
```php
97+
use TheCodingMachine\CacheUtils\FileBoundCache;
98+
use TheCodingMachine\CacheUtils\ClassBoundCache;
99+
use TheCodingMachine\CacheUtils\ClassBoundMemoryAdapter;
100+
use TheCodingMachine\CacheUtils\ClassBoundCacheContract;
101+
102+
$fileBoundCache = new FileBoundCache($psr16Cache);
103+
$classBoundCache = new ClassBoundMemoryAdapter(new ClassBoundCache($psr16Cache));
104+
$classBoundCacheContract = new ClassBoundCacheContract(new ClassBoundCache($fileBoundCache));
105+
106+
// Put the $myDataToCache object in cache.
107+
// If the FooBar class is modified, the cache item is purged.
108+
$classBoundCache->get(new ReflectionClass(FooBar::class), function() {
109+
// let's return the item to be cached.
110+
// this function is called only if the item is not in cache yet.
111+
});
112+
```
113+
114+
With cache contracts, there is not setters. Only a getter that takes in parameter a callable that will resolve the
115+
cache item if the item is not available in the cache.

src/ClassBoundCacheContract.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
4+
namespace TheCodingMachine\CacheUtils;
5+
6+
use ReflectionClass;
7+
8+
class ClassBoundCacheContract implements ClassBoundCacheContractInterface
9+
{
10+
/**
11+
* @var ClassBoundCacheInterface
12+
*/
13+
private $classBoundCache;
14+
15+
public function __construct(ClassBoundCacheInterface $classBoundCache)
16+
{
17+
$this->classBoundCache = $classBoundCache;
18+
}
19+
20+
/**
21+
* @param ReflectionClass $reflectionClass
22+
* @param callable $resolver
23+
* @param string|null $key An optional key to differentiate between cache items attached to the same class.
24+
* @return mixed
25+
*/
26+
public function get(ReflectionClass $reflectionClass, callable $resolver, string $key = '')
27+
{
28+
$cacheKey = $reflectionClass->getName().'__'.$key;
29+
$item = $this->classBoundCache->get($cacheKey);
30+
if ($item !== null) {
31+
return $item;
32+
}
33+
34+
$item = $resolver();
35+
36+
$this->classBoundCache->set($cacheKey, $item, $reflectionClass);
37+
38+
return $item;
39+
}
40+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace TheCodingMachine\CacheUtils;
4+
5+
use ReflectionClass;
6+
7+
interface ClassBoundCacheContractInterface
8+
{
9+
/**
10+
* @param ReflectionClass $reflectionClass
11+
* @param callable $resolver
12+
* @param string|null $key An optional key to differentiate between cache items attached to the same class.
13+
* @return mixed
14+
*/
15+
public function get(ReflectionClass $reflectionClass, callable $resolver, string $key = '');
16+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
namespace TheCodingMachine\CacheUtils;
4+
5+
use function clearstatcache;
6+
use PHPUnit\Framework\TestCase;
7+
use ReflectionClass;
8+
use function sleep;
9+
use Symfony\Component\Cache\Simple\ArrayCache;
10+
use TheCodingMachine\CacheUtils\Fixtures\A;
11+
use function touch;
12+
13+
class ClassBoundCacheContractTest extends TestCase
14+
{
15+
public function testClassBoundCacheContract()
16+
{
17+
$cache = new ArrayCache();
18+
$fileBoundCache = new FileBoundCache($cache, 'prefix');
19+
$classBoundCache = new ClassBoundCache($fileBoundCache, true, true, true);
20+
$classBoundCacheContract = new ClassBoundCacheContract($classBoundCache);
21+
22+
$val = 0;
23+
24+
$newVal = $classBoundCacheContract->get(new ReflectionClass(A::class), function() use (&$val) {
25+
return ++$val;
26+
});
27+
28+
$this->assertSame(1, $newVal);
29+
30+
$newVal2 = $classBoundCacheContract->get(new ReflectionClass(A::class), function() use (&$val) {
31+
return ++$val;
32+
});
33+
34+
$this->assertSame(1, $newVal2);
35+
36+
$classToTouch = new ReflectionClass(A::class);
37+
sleep(1);
38+
clearstatcache($classToTouch->getFileName());
39+
touch($classToTouch->getFileName());
40+
41+
$newVal3 = $classBoundCacheContract->get(new ReflectionClass(A::class), function() use (&$val) {
42+
return ++$val;
43+
});
44+
45+
$this->assertSame(2, $newVal3);
46+
}
47+
48+
}

tests/ClassBoundCacheTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class ClassBoundCacheTest extends TestCase
2222
/**
2323
* @dataProvider touchFile
2424
*/
25-
public function testFileBoundCache($classToTouch)
25+
public function testClassBoundCache($classToTouch)
2626
{
2727
$cache = new ArrayCache();
2828
$fileBoundCache = new FileBoundCache($cache, 'prefix');

0 commit comments

Comments
 (0)