Skip to content

Commit a6e4128

Browse files
refactor and cs fixtures
1 parent fc792b4 commit a6e4128

File tree

9 files changed

+588
-320
lines changed

9 files changed

+588
-320
lines changed

CHANGELOG.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,19 @@
22

33
All notable changes to `biurad/biurad-caching` will be documented in this file.
44

5-
# 0.2.5 - 2020-06-16
5+
## 0.2.5 - 2020-06-16
6+
67
- Added support for php 7.4 preloading feature.
7-
- Added support for adding caching drivers on Nette and BiuradPHP frameworks.
88
- Added psr-6 caching support and adapter system
99
- Added phpunit tests
1010
- Improved code complexity and performance.
1111
- Lifted php minimum version to 7.1 due to support for psr-6
1212
- Fixed minor issues regarding caching.
1313
- Updated php files header doc
14+
- Updated README.md file
15+
16+
## 0.2.1 - 2020-05-04
1417

15-
# 0.2.1 - 2020-05-04
1618
- Improved code quality to prevent breaks and better performance
1719
- Added support for *var_export* caching using the new *MemoryCache* class
1820
- Added Doctrine's *PhpFileCache* adapter as *memory* cache adapter
@@ -24,6 +26,7 @@ All notable changes to `biurad/biurad-caching` will be documented in this file.
2426
- Updated README.md file
2527

2628
## 0.1.10 - 2020-03-28
29+
2730
- Added doctrine cache adapter *Memcached*
2831

2932
## 0.1.9 - 2020-02-27

README.md

Lines changed: 196 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
# Cache manager using Doctrine Cache with easy-to-use PSR-16 API for quick caching
1+
# Cache manager using Doctrine Cache, offers a very intuitive PSR-16 and PSR-6 API for cache manipulation.
22

3-
Cache accelerates your application by storing data - once hardly retrieved - for future use. The caching manager focuses on [Doctrine Cache](https://github.com/doctrine/cache) for caching. [Cache](https://github.com/cache/cache) will be supported in the future.
4-
5-
Cache manager utilizes PSR-16 protocols to allow your application to communicate with cache engines. For now let's work with [Doctrine Cache](https://github.com/doctrine/cache).
3+
The Cache manager is a [Doctrine Cache](https://github.com/doctrine/cache) based system, providing features covering simple to advanced caching needs. Natively implements PSR-6 and PSR-16 for greatest interoperability. It is designed for performance and resiliency. It enables concurrent caching, cache stampede protection via locking early expiration and more advanced caching stragegies.
64

75
**`Please note that this documentation is currently work-in-progress. Feel free to contribute.`**
86

@@ -14,84 +12,242 @@ The recommended way to install Cache Manager is via Composer:
1412
composer require biurad/biurad-caching
1513
```
1614

17-
It requires PHP version 7.0 and supports PHP up to 7.4. The dev-master version requires PHP 7.1.
15+
It requires PHP version 7.1 and supports PHP up to 7.4. The dev-master version requires PHP 7.1.
1816

1917
## How To Use
2018

2119
Cache manager offers a very intuitive API for cache manipulation. Before we show you the first example, we need to think about place where
2220
to store data physically. We can use a database, Memcached server, or the most available storage - hard drive. So we thought of using [Doctrine Cache](https://github.com/doctrine/cache) implementation:
2321

2422
```php
25-
// the `temp` directory will be the storage
23+
// you can use any of doctrine cache adapter
2624
$storage = new Doctrine\Common\Cache\ArrayCache();
2725
```
2826

29-
The `Doctrine\Common\Cache\Cache` storage is very well optimized for performance and in the first place,
30-
it provides full atomicity of operations.
27+
The `Doctrine\Common\Cache\Cache` storage is very well optimized for performance and in the first place, it provides full atomicity of operations.
28+
29+
What does that mean? When we use cache we can be sure we are not reading a file that is not fully written yet (by another thread) or that the file gets deleted "under our hands". Using the cache is therefore completely safe.
30+
31+
The package has 5 important strategies for caching, thus:
32+
33+
Strategy | Description
34+
--- | ---
35+
BiuradPHP\Cache\SimpleCache | For PSR-16 caching abilities using doctrine cache adapter
36+
BiuradPHP\Cache\CacheItemPool | For PSR-6 caching abilities
37+
BiuradPHP\Cache\FastCache | For advance and optimized PSR-16/PSR-6 caching strategy
38+
BiuradPHP\Cache\MemoryCache | For caching using `var_export`
39+
BiuradPHP\Cache\Preloader | For php7.4 opache.preload abilities
40+
41+
Now you can create, retrieve, update and delete items using the above caching classes except `Preloader` class:
42+
43+
> For manipulation with cache using psr-16, we use the `BiuradPHP\Cache\SimpleCache`:
44+
---
45+
46+
```php
47+
use BiuradPHP\Cache\SimpleCache;
48+
49+
$cache = new SimpleCache($storage); // psr-16 caching
50+
```
51+
52+
```php
53+
// assign a value to the item and save it
54+
$cache->set('stats.products_count', 4711);
55+
56+
// retrieve the cache item
57+
$productsCount = $cache->get('stats.products_count');
58+
59+
if (null === $productsCount) {
60+
// ... item does not exist in the cache
61+
}
62+
63+
// retrieve the value stored by the item
64+
$total = $productsCount;
65+
66+
// remove the cache item
67+
$cache->delete('stats.products_count');
68+
```
69+
70+
If you want a quick caching strategy for your application, use PSR-16 caching strategy. Its so simple and straight forward.
71+
72+
> For manipulation with cache using psr-16, we use the `BiuradPHP\Cache\CacheItemPool`:
73+
---
74+
75+
```php
76+
use BiuradPHP\Cache\CacheItemPool;
77+
78+
$cache = new CacheItemPool($cache); // psr-16 cache in psr-6 cache.
79+
```
80+
81+
```php
82+
// create a new item by trying to get it from the cache
83+
$productsCount = $cache->getItem('stats.products_count');
84+
85+
// assign a value to the item and save it
86+
$productsCount->set(4711);
87+
$cache->save($productsCount);
88+
89+
// retrieve the cache item
90+
$productsCount = $cache->getItem('stats.products_count');
91+
92+
if (!$productsCount->isHit()) {
93+
// ... item does not exist in the cache
94+
}
95+
96+
// retrieve the value stored by the item
97+
$total = $productsCount->get();
98+
99+
// remove the cache item
100+
$cache->deleteItem('stats.products_count');
101+
```
102+
103+
If you want a bit advanced caching stratagy above PSR-16, PSR-6 is what you need, has a cool way of invalidating a missed cache.
104+
105+
> For manipulation with cache using `var_export`, we use the `BiuradPHP\Cache\MemoryCache`:
106+
---
107+
108+
```php
109+
use BiuradPHP\Cache\MemoryCache;
110+
111+
$cache = new MemoryCache(getcwd() . '/memory_cache');
112+
```
113+
114+
```php
115+
// assign a value to the item and save it
116+
$products = [...]; // An array of products
117+
$cache->saveData('stats.products', $products);
31118

32-
What does that mean? When we use cache we can be sure we are not reading a file that is not fully
33-
written yet (by another thread) or that the file gets deleted "under our hands". Using the cache is therefore completely safe.
119+
if (null === $productsCount) {
120+
// ... item does not exist in the cache
121+
}
34122

35-
For manipulation with cache, we use the `BiuradPHP\Cache\SimpleCache`:
123+
// retrieve the value stored by the item
124+
$total = $cache->loadData('stats.products');
125+
126+
// Remove cache item, by deleting the cache file.
127+
```
128+
129+
> For manipulation with cache using advanced PSR-6, we use the `BiuradPHP\Cache\FastCache`:
130+
---
131+
132+
For each method in `BiuradPHP\Cache\FastCache` class that has a second parameter `callable`, which is called when there is no such item in the cache. This callback receives 2 arguments at the end by reference. The `Psr\Cache\CacheItemInterface` and a boolean, which you can use for setting expiration rules and saving data into cache.
36133

37134
```php
135+
use BiuradPHP\Cache\CacheItemPool;
38136
use BiuradPHP\Cache\SimpleCache;
39-
use BiuradPHP\Cache\FastCache as Caching;
137+
use BiuradPHP\Cache\FastCache;
138+
139+
// you can use any of doctrine cache adapter
140+
$storage = new Doctrine\Common\Cache\ArrayCache();
141+
142+
$psr6 = new CacheItemPool($psr16 = new SimpleCache($storage)); // psr-16 cache in psr-6 cache.
143+
144+
$cache = new FastCache($psr16);
40145

41-
$psr = new SimpleCache($storage); // $storage from the previous example
42-
$cache = new Caching($psr);
146+
//or
147+
$cache = new FastCache($psr6);
43148
```
44149

45-
Let's save the contents of the '`$data`' variable under the '`$key`' key:
150+
The first argument of the load() method is a key, an arbitrary string that you associate to the cached value so you can retrieve it later. The second argument is a PHP callable which is executed when the key is not found in the cache to generate and return the value:
46151

47152
```php
48-
$cache->save($key, $data);
153+
use Psr\Cache\CacheItemIterface;
154+
155+
// The callable will only be executed on a cache miss.
156+
$value = $cache->load('my_cache_key', function (CacheItemInterface $item) {
157+
$item->expiresAfter(3600);
158+
159+
// ... do some HTTP request or heavy computations
160+
$computedValue = 'foobar';
161+
162+
return $computedValue;
163+
});
164+
165+
echo $value; // 'foobar'
166+
167+
// ... and to remove the cache key
168+
$cache->delete('my_cache_key');
49169
```
50170

51-
This way, we can read from the cache: (if there is no such item in the cache, the `null` value is returned)
171+
The callable caching feature. Caching the result of a function or method call can be achieved using the `call()` method:
52172

53173
```php
54-
$value = $cache->load($key);
55-
if ($value === null) ...
174+
$name = $cache->call('gethostbyaddr', $ip);
56175
```
57176

58-
Method `get()` has second parameter `callable` `$fallback`, which is called when there is no such item in the cache. This callback receives the array *$dependencies* by reference, which you can use for setting expiration rules.
177+
The `gethostbyaddr($ip)` will, therefore, be called only once and next time, only the value from cache will be returned. Of course, for different `$ip`, different results are cached. But if you want to set expiry time on call, add `Psr\Cache\CacheItemInterface` argument at the end and set the expiration time.
178+
179+
Similarly, it is possible to wrap a function with cache and call it later.
59180

60181
```php
61-
$cache->save($key, function(& $dependencies) {
62-
// some calculation
63-
64-
return 15;
65-
}));
182+
function calculate($number)
183+
{
184+
return 'number is ' . $number;
185+
}
186+
187+
$wrapper = $cache->wrap('calculate');
66188

67-
$value = $cache->load($key);
189+
$result = $wrapper(1); // number is 1
190+
$result = $wrapper(2); // number is 2
68191
```
69192

70-
We could delete the item from the cache either by saving null or by calling `delete()` method:
193+
The template/output caching feature. Caching the result of an output can be cached not only in templates:
71194

72195
```php
73-
$cache->save($key, null);
74-
// or
75-
$cache->remove($key);
196+
if ($block = $cache->start($key)) {
197+
... printing some data ...
198+
199+
$block->end(); // save the output to the cache
200+
}
76201
```
77202

78-
It's possible to save any structure to the cache, not only strings. The same applies for keys.
203+
In case that the output is already present in the cache, the `start()` method prints it and returns `null`. Otherwise, it starts to buffer the output and returns the `$block` object using which we finally save the data to the cache.
79204

80-
Deleting the cache is a common operation when uploading a new application version to the server. At that moment, however, using [Doctrine Cache](https://github.com/doctrine/cache), the server can handle it's operations.
81-
because it has to build a complete new cache. Retrieving some data is not difficult, cause [Doctrine Cache](https://github.com/doctrine/cache) create temporary memory data, so you don't run into further errors. If you are experiencing difficulties in caching.
205+
The expiration and invalidation caching feature.
82206

83-
The solution is to modify application behaviour so that data are created only by one thread and others are waiting. To do this, specify the value as a callback
84-
or use an anonymous function:
207+
This feature works with only PSR-6 cache, By default the beta is 1.0 and higher values mean earlier recompute. Set it to 0 to disable early recompute and set it to INF to force an immediate recompute:
85208

86209
```php
87-
$result = $cache->save($key, function() {
210+
use Psr\Cache\CacheItemIterface;
88211

89-
return buildData(); // difficult operation
90-
});
212+
$beta = 1.0;
213+
$value = $cache->save('my_cache_key', function (CacheItemInterface $item) {
214+
$item->expiresAfter(3600);
215+
216+
return '...';
217+
}, $beta);
218+
```
219+
220+
If you want more control over caching any php type except closures, this package is just for you. This package implements [Stampede prevention](https://en.wikipedia.org/wiki/Cache_stampede), concurrent caching and works perfectly with either PSR-6 or PSR-16 cache.
221+
222+
> For manipulation of php 7.4 opcache preload feature, we use the `BiuradPHP\Cache\Preloader`:
223+
---
224+
225+
```php
226+
use BiuradPHP\Cache\Preloader;
227+
228+
$preloadClasses = [...]; // A list array of classes to be appended for preloading.
229+
$preloadFile = getcwd().'/opcache.preload.php'; // The file preloaded classes to fetch from.
230+
231+
Preloader::append($preloadFile, $preloadClasses);
232+
233+
// to check opcache preload statistics
234+
var_dump(Preloader::getStatistics());
235+
```
236+
237+
After the `$preloadFile` is written into, set the following configuration in your php.ini file:
238+
239+
```ini
240+
; php.ini
241+
opcache.preload=/path/to/opcache.preload.php
242+
243+
; maximum memory that OPcache can use to store compiled PHP files
244+
opcache.memory_consumption=256
245+
246+
; maximum number of files that can be stored in the cache
247+
opcache.max_accelerated_files=20000
91248
```
92249

93-
The Cache-manager will ensure that the body of the function will be called only by one thread at once, and other threads will be waiting.
94-
If the thread fails for some reason, another gets chance.
250+
Starting from PHP 7.4, OPcache can compile and load classes at start-up and make them available to all requests until the server is restarted, improving performance significantly.
95251

96252
## Changelog
97253

src/Bridges/CacheExtension.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,14 @@ public function loadConfiguration(): void
7979
->setConfig($this->config)
8080
->withDefault($this->config->driver)
8181
->getDefinition($this->prefix('doctrine'))
82-
->setType(Cache::class)
83-
;
82+
->setType(Cache::class);
8483

85-
$builder->addDefinition($this->prefix('psr'))
86-
->setFactory(BiuradPHP\Cache\SimpleCache::class)
87-
;
84+
$builder->addDefinition($this->prefix('psr16'))
85+
->setFactory(BiuradPHP\Cache\SimpleCache::class);
8886

89-
$builder->addAlias('cache', $this->prefix('psr'));
87+
$builder->addDefinition($this->prefix('psr6'))
88+
->setFactory(BiuradPHP\Cache\CacheItemPool::class);
89+
90+
$builder->addAlias('cache', $this->prefix('psr16'));
9091
}
9192
}

src/CacheItem.php

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@
1717

1818
namespace BiuradPHP\Cache;
1919

20+
use BiuradPHP\Cache\Exceptions\InvalidArgumentException;
2021
use DateInterval;
2122
use DateTime;
2223
use DateTimeInterface;
2324
use Psr\Cache\CacheItemInterface;
24-
use Psr\Cache\InvalidArgumentException;
2525

2626
final class CacheItem implements CacheItemInterface
2727
{
@@ -39,6 +39,7 @@ final class CacheItem implements CacheItemInterface
3939
/** @var bool */
4040
protected $isHit = false;
4141

42+
/** @var int|float */
4243
protected $expiry;
4344

4445
/** @var int */
@@ -118,11 +119,6 @@ public function expiresAfter($time): self
118119
return $this;
119120
}
120121

121-
public function getExpires(): ?int
122-
{
123-
return $this->expiry;
124-
}
125-
126122
/**
127123
* Validates a cache key according to PSR-6 and PSR-16.
128124
*

src/CacheItemPool.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use BadMethodCallException;
2121
use Closure;
2222
use Exception;
23+
use Generator;
2324
use Psr\Cache\CacheItemInterface;
2425
use Psr\Cache\CacheItemPoolInterface;
2526
use Psr\SimpleCache\CacheInterface;
@@ -354,7 +355,13 @@ public function commit()
354355
*/
355356
protected function doFetch(array $ids)
356357
{
357-
foreach ($this->pool->getMultiple($ids, $this->miss) as $key => $value) {
358+
$fetched = $this->pool->getMultiple($ids, $this->miss);
359+
360+
if ($fetched instanceof Generator) {
361+
$fetched = $fetched->getReturn();
362+
}
363+
364+
foreach ($fetched as $key => $value) {
358365
if ($this->miss !== $value) {
359366
yield $key => $value;
360367
}

0 commit comments

Comments
 (0)