germania-kg / cachecallable
Callable convenience wrapper around PSR-6 Cache Item Pools: Seamlessly create, return, and store your data.
Installs: 1 059
Dependents: 3
Suggesters: 0
Security: 0
Stars: 0
Watchers: 4
Forks: 0
Open Issues: 1
Requires (Dev)
- friendsofphp/php-cs-fixer: ^2.0|^3.0
- php-coveralls/php-coveralls: ^2.0
- phpspec/prophecy-phpunit: ^2.0
- phpstan/phpstan: ^1.9
- phpunit/phpunit: ^8.0|^9.0
- spatie/phpunit-watcher: ^1.0
- symfony/cache: ^5.0
Suggests
- symfony/cache: Symfony's Caching Library
- tedivm/stash: PHP Caching Library
This package is auto-updated.
Last update: 2024-12-04 18:52:33 UTC
README
Callable convenience wrapper around PSR-6 Cache Item Pools: Seamlessly creates, returns, and stores your data.
Caching business is pretty much always similar and can be outlined like this:
- Is caching enabled at all? If not, delete any according older entry first.
Create and return fresh content anyway, ending up here. - Does a given item exist? If so, return item content;
Otherwise, create, store and return content.
The CacheCallable class reduces these steps to a handy and customizable Callable.
Installation with Composer
$ composer require germania-kg/cachecallable
Example
Although this example uses phpfastcache, you should be able to pass in any Cache Item Pool. Use your favourite PSR-3 Logger; this example will use the well-known Monolog.
<?php use phpFastCache\CacheManager; use Monolog\Logger; use Germania\Cache\CacheCallable; // Setup dependencies $cacheItemPool = CacheManager::getInstance('files', [ options ]); $lifetime = 3600; $monolog = new Logger( "My App" ); $content_creator = function( $keyword ) { return "Cache keyword: " . $keyword; }; // // Setup Cache wrapper // $wrapped_cache = new CacheCallable( $cacheItemPool, $lifetime, $creator, $monolog // optional ); // Identifying key. Example for a web page: $keyword = sha1($_SERVER['REQUEST_URI']); echo $wrapped_cache( $keyword );
A word on cache keys
According to the PSR-6 specs, cache keys should be limited to A-Z, a-z, 0-9, _, and .
to ensure maximum compatibilty. So if you pass in a PSR-6 Adapter from Symfony Cache component, class CacheCallable internally converts the given keys to a MD5 representation.
In case you'd like to provide a custom cache key creation, you may use the setCacheKeyCreator method whoch accepts any callable:
$wrapped_cache->setCacheKeyCreator( function($raw) { return sha1($raw); } );
PHP-FIG: PSR-6: Caching Interface
Implementing libraries MUST support keys consisting of the characters A-Z, a-z, 0-9, _, and . in any order in UTF-8 encoding and a length of up to 64 characters. Implementing libraries MAY support additional characters and encodings or longer lengths, but must support at least that minimum.
Symfony docs: “Cache Item Keys and Values”
The key of a cache item […] should only contain letters (A-Z, a-z), numbers (0-9) and the _ and . symbols.
The Cache lifetime
Think of a webpage that turns out to be not cached during script runtime — after we set up the Cache wrapper. For this reason, the Cache wrapper constructor also accepts a LifeTimeInterface implementation with a getValue method:
<?php namespace Germania\Cache; interface LifeTimeInterface { // Return seconds to expiration public function getValue(); }
The LifeTime class is a simple implementation of this interface. It additionally enables you to change the lifetime value during runtime. Since we passed it to our Cache constructor by reference, the Cache wrapper can decide after content creation wether to cache or not.
Create a Lifetime object
<?php use Germania\Cache\CacheCallable; use Germania\Cache\LifeTime; // Setup LifeTime object $lifetime_object = new LifeTime( 3600 ); // Use Factory method: $lifetime_object = LifeTime::create( 3600 ); // Create from Lifetime instance $another_lifetime = new LifeTime( $lifetime_object ); $another_lifetime = LifeTime::create( $lifetime_object );
Usage with CacheCallable
<?php use Germania\Cache\CacheCallable; use Germania\Cache\LifeTime; // Taken from example above $wrapped_cache = new CacheCallable( $cacheItemPool, $lifetime_object, $creator );
Your Logger will now output something like this:
MyLogger DEBUG Lifetime after content creation: 0
MyLogger NOTICE DO NOT store in cache
How to change lifetime during script runtime
After instantation, you may use the setValue method:
<?php namespace Germania\Cache; interface LifeTimeInterface { // Return seconds to expiration public function getValue(); }
The LifeTime class is a simple implementation of this interface. It additionally enables you to change the lifetime value during runtime. Since we passed it to our Cache constructor by reference, the Cache wrapper can decide after content creation wether to cache or not.
Create a Lifetime object:
<?php use Germania\Cache\CacheCallable; use Germania\Cache\LifeTime; // Setup LifeTime object $lifetime_object = new LifeTime( 3600 ); // Use Factory method: $lifetime_object = LifeTime::create( 3600 ); // Create from Lifetime instance $another_lifetime = new LifeTime( $lifetime_object ); $another_lifetime = LifeTime::create( $lifetime_object );
Set time value after instantation
// Change LifeTime value during runtime, // e.g. in router or controller $lifetime_object->setValue( 0 );
Usage with CacheCallable
<?php use Germania\Cache\CacheCallable; use Germania\Cache\LifeTime; // Taken from example above $wrapped_cache = new CacheCallable( $cacheItemPool, $lifetime_object, $creator );
Your Logger will now output something like this:
MyLogger DEBUG Lifetime after content creation: 0
MyLogger NOTICE DO NOT store in cache
How to override content creation
If you prefer singleton services, you may invoke the CacheCallable with a custom content creator parameter to override the default one:
// Default content creator $default_creator = function($file) { return json_decode( file_get_contents($file) ); }; // Setup Service $wrapped_cache = new CacheCallable( $cacheItemPool, $lifetime_object, $default_creator ); // Override content creation $config = $wrapped_cache("config.json", function( $file ) { return array('foo' => 'bar'); };
Issues
The PSR-6 Caching Interface mock in CacheCallableTest could need an overhaul. Discuss on #issue 3
Development
$ git clone https://github.com/GermaniaKG/CacheCallable.git
$ cd CacheCallable
$ composer install
Unit tests
Either copy phpunit.xml.dist
to phpunit.xml
and adapt to your needs, or leave as is. Run PhpUnit test or composer scripts like this:
$ composer test # or $ vendor/bin/phpunit