thomas-institut/datacache

Cache abstraction and basic implementation

v1.0.1 2025-04-22 09:30 UTC

This package is auto-updated.

Last update: 2025-05-09 08:18:49 UTC


README

Latest Stable Version Test GitHub License

Dynamic JSON Badge

This package provides an interface to a cache that can store strings. It also provides three simple, yet effective implementations.

Implementations MUST pass all tests in the included DataCacheReferenceTest

DataCache Interface

class MyDataCache implements DataCache {
// ...
}

$cache = new MyDataCache(...);

To cache a string with the cache's default TTL:

$cache->set('someKey', 'someValue'); 

There are no restrictions on the characters that can be used as a key or value: any character is allowed (including non-printable ones) and there is no set maximum length.

Implementations MUST support arbitrary characters in keys and values but MAY impose some limits to key and value lengths. Implementations MUST support maximum key lengths of at least 2048 characters and maximum value lengths of at least 32 megabytes.

Implementations decide what is the default TTL when the user has not specified one. The default TTL can be set at any time with:

$cache->setDefaultTtl($newDefaultTtl); 

TTLs are given in seconds. A TTL of 0 seconds means that items will not expire. If a negative TTL is given to the setDefaultTtl method, no changes will be made to the current default TTL.

The default TTL can be overridden when setting a value:

$cache->set('someKey', 'someValue', $customTtl); 

where $customTtl is given in seconds. A TTL equal to zero instructs the cache to never expire the item, while a negative TTL is ignored (and the default TTL will be used).

The value of a cached item can be retrieved with:

$value = $cache->get('someKey');

If the item is not in the cache, the get method will throw an ItemNotInCacheException.

To check if an item is in the case without necessarily retrieving it, use the following convenience method:

$exists = $cache->isInCache('someKey');

However, implementations may still have to retrieve the item to test for existence, so it cannot be generally assumed that the isInCache method is more efficient.

Some implementations may be able to report the remaining TTL for an item:

$remainingTtl = $cache->getRemainingTtl('someKey');

If the cache does not support reporting remaining TTLs, this method returns -1. Otherwise, it returns the number of seconds until the item's expiration or 0 if the item will never expire.

To delete an item:

$cache->delete('someKey');

The delete method returns silently if the item is not in the cache.

All the items in the cache can be deleted at once with the flush method:

$cache->flush();

Depending on the implementation, a cache flush may delete everything in the cache, including items that were stored in the same underlying storage or service by other DataCache instances or by any other means. The only mandatory behaviour is that all items set by the cache instance must not be accessible after a flush.

Some implementations may also be able to clean the cache by releasing memory or storage space for items that are already expired:

$cache->clean();

If the implementation does not support cleaning or if manual cleaning is not available for the cache, the clean method will return silently and nothing will happen.

InMemoryDataCache

InMemoryDataCache is a DataCache implementation that uses a PHP array to store item values.

The constructor does not have any parameters:

$cache = new InMemoryDataCache();

This cache supports arbitrary length keys and values, can report remaining TTLs and will only remove expired items from the underlying PHP array when explicitly deleted or when the clean or flush methods are called.

When the instance is destroyed, all cached items will be destroyed as well.

DirectoryDataCache

DirectoryDataCache is a DataCache that stores each individual item's value in a file in a given directory. That is, every item generates one separate file that contains the value of the item. As such, the cache's content will persist after instances are destroyed, and items can be deleted manually by simply deleting their corresponding files.

$cache = new DirectoryDataCache('/path/to/directory', $cacheName);

$cacheName is a string that identifies the cache. It is used as a filename prefix for the files generated by the cache. This allows to have multiple independent caches in the same directory.

The file name for a cached item has the following form:

$directoryPath . '/' . $cacheName . $sep . $keyOrHash . $sep . $exp . '.' . $ext 

where $sep is a separator character (by default '-') and $ext is a file extension (by default 'txt').

By default, $keyOrHash is the item's key if the key does not contain the separator nor any character that the file system does not allow in file name. Otherwise, a hash of the key will be used instead.

$exp is the Unix timestamp after which the item is no longer valid.

The constructor has three more optional parameters to control file names:

  • the file extension to use for all files (default 'txt'). It can be empty.
  • the character to use as field separator in file name (default '-'). The characters * and / cannot be used as separators. If the file extension is not empty, the dot cannot be used either.
  • a boolean flag that instructs the cache to ALWAYS use the hash of an item's key in the file name (default false).

DirectoryDataCache supports arbitrary length keys and values, does NOT report remaining TTLs and will only delete files from disk when items are explicitly deleted or when the clean or flush methods are called.

MultiCacheDataCache

MultiCacheDataCache is a DataCache that aggregates a list of DataCache instances. When an item is stored, it is stored in all caches and when it is deleted it is deleted from all caches as well. However, when an item is retrieved, it is only retrieved from the first cache in the list that has it.

The intended use of this cache is setting up faster caches in the first positions in the list and slower, perhaps persistent caches, in the latter positions. Reads will normally be handled by the faster caches, while the slower, persistent caches are used as backup.

The constructor requires an array of cache instances or callables that return a cache instance, an optional array of key prefixes to attach to keys in the corresponding caches and an optional boolean flag that when true, instructs the cache to use an InMemoryDataCache when a cache callable fails (by default this flag is false)

$cache = new MultiCacheDataCache( [ $cache1, $callable2, $cache3 ...]);

$cache2 = new MultiCacheDataCache( 
    [ $cache1, $callable2, ...], 
    [ 'prefix1', 'prefix2', ...], true);

CacheAware Interface

CacheAware is an interface that provides common functions that allow clients to control caching in the class: set the cache with an instance of a DataCache implementation or with a callable, start and stop using the cache and tell whether the cache is in use or not.

class MyCacheAware  implements CacheAware { 
  
    public function someMethod() {
     
         // ...
        if ($this->isCacheInUse()) {
            // do something with the cache
            $this->getDataCache()->set(...);
        }
    }
}


$myInstance = new MyCacheWare(...);

$myInstance->setCache($someDataCacheInstanceOrSomeCallable);

$myInstance->useCache();
$myInstance->someMethod();  // cache will be used

$myInstance->doNotUseCache();
$myInstance->someMethod(); // cache will not be used

The trait SimpleCacheAwareTrait provided in this package implements this interface.