Giter VIP home page Giter VIP logo

cache's Introduction

Apix Cache, cache-tagging for PHP Build Status

Latest Stable Version Total Downloads Build Status Code Quality Code Coverage License

Apix Cache is a generic and thin cache wrapper with a PSR-6 interface to various caching backends and emphasising cache tagging and indexing.

Cache-tagging allows to find/update all data items with one or more given tags. Providing, for instance, a batch delete of all obsolete entries matching a speficic tag such as a version string.

  • Fully unit-tested and compliant with PSR-1, PSR-2, PSR-4 and PSR-6 (Cache).
  • Continuously integrated
    • against PHP 5.3, 5.4, 5.5, 5.6, 7.0, 7.1, 7.2, 7.3 and HHVM,
    • and against APC, APCu, Redis, MongoDB, Sqlite, MySQL, PgSQL and Memcached, ...
    • supports a range of serializers: igBinary, msgpack, json, php, ...
  • Extendable, additional extensions are available:
    • apix/simple-cache provides a SimpleCache (PSR-16) interface.
    • More contributions will be linked here.
  • Available as a Composer and as a PEAR package.

Pull requests and ★ Stars are always welcome. For bugs and feature request, please create an issue.


Cache backends

Currently, the following cache store are supplied:

Factory usage (PSR-Cache wrapper)

  use Apix\Cache;

  $backend = new \Redis();
  #$backend = new \PDO('sqlite:...');    // Any supported client object e.g. Memcached, MongoClient, ...
  #$backend = new Cache\Files($options); // or one that implements Apix\Cache\Adapter
  #$backend = 'apcu';                    // or an adapter name (string) e.g. "APC", "Runtime"
  #$backend = new MyArrayObject();       // or even a plain array() or \ArrayObject.

  $cache = Cache\Factory::getPool($backend);             // without tagging support
  #$cache = Cache\Factory::getTaggablePool($backend);    // with tagging
  
  $item = $cache->getItem('wibble_id');
  
  if ( !$cache->isHit() ) {
    $data = compute_expensive_stuff();
    $item->set($data);
    $cache->save($item);
  }

  return $item->get();

Basic usage (Apix native)

  use Apix\Cache;

  $cache = new Cache\Apcu;

  // try to retrieve 'wibble_id' from the cache
  if ( !$data = $cache->load('wibble_id') ) {
    
    // otherwise, get some data from the origin
    // example of arbitrary mixed data
    $data = array('foo' => 'bar');

    // and save it to the cache
    $cache->save($data, 'wibble_id');
  }

You can also use the folowing in your use cases:

  // save $data to the cache as 'wobble_id',
  // tagging it along the way as 'baz' and 'flob',
  // and set the ttl to 300 seconds (5 minutes)
  $cache->save($data, 'wobble_id', array('baz', 'flob'), 300);

  // retrieve all the cache ids under the tag 'baz'
  $ids = $cache->loadTag('baz');

  // clear out all items with a 'baz' tag
  $cache->clean('baz');

  // remove the named item
  $cache->delete('wibble_id');

  // flush out the cache (of all -your- stored items)
  $cache->flush();

Advanced usage

Options shared by all the backends

  use Apix\Cache;
  
  // default options
  $options = array(
      'prefix_key'  => 'apix-cache-key:', // prefix cache keys
      'prefix_tag'  => 'apix-cache-tag:', // prefix cache tags
      'tag_enable'  => true               // wether to enable tags support
  );

  // start APCu as a local cache
  $local_cache = new Cache\Apcu($options);

Redis specific

  // additional (default) options
  $options['atomicity']  = false;   // false is faster, true is guaranteed
  $options['serializer'] = 'php';   // null, php, igbinary, json and msgpack

  $redis_client = new \Redis;       // instantiate phpredis*
  $distributed_cache = new Cache\Redis($redis_client, $options);

* see PhpRedis for instantiation usage.

Memcached specific

  // additional (default) options, specific to Memcached
  $options['prefix_key'] = 'key_';  // prefix cache keys
  $options['prefix_tag'] = 'tag_';  // prefix cache tags
  $options['prefix_idx'] = 'idx_';  // prefix cache indexes
  $options['prefix_nsp'] = 'nsp_';  // prefix cache namespaces
  $options['serializer'] = 'auto';  // auto, igbinary, msgpack, php, json and json_array.

  $memcached  = new \Memcached;     // a Memcached*** instance
  $shared_cache = new Cache\Memcached($memcached, $options);

The serialzer auto (default) is igBinary if available, then msgpack if available, then php otherwise.

*** see Memcached for instantiation details.

MongoDB specific

  // additional (default) options
  $options['object_serializer'] = 'php';  // null, json, php, igBinary
  $options['db_name'] = 'apix';           // name of the mongo db
  $options['collection_name'] = 'cache';  // name of the mongo collection

  $mongo  = new \MongoDB\Client;          // MongoDB native driver
  #$mongo  = new \MongoClient;            // or MongoDB legacy driver
  $cache = new Cache\Mongo($mongo, $options);

PDO specific

  // additional (default) options, specific to the PDO backends
  $options['db_table']   = 'cache';       // table to hold the cache
  $options['serializer'] = 'php';         // null, php, igbinary, json and msgpack
  $options['preflight']  = true;          // wether to preflight the DB
  $options['timestamp']  = 'Y-m-d H:i:s'; // the timestamp DB format

  // with SQLITE
  $dbh = new \PDO('sqlite:/tmp/apix_tests.sqlite3');
  $relational_cache = new Cache\Pdo\Sqlite($dbh, $options);

  // with MYSQL, MariaDB and Percona
  $dbh = new \PDO('mysql:host=xxx;port=xxx;dbname=xxx', 'user', 'pass');
  $mysql_cache = new Cache\Pdo\Mysql($dbh, $options);

  // with PGSQL
  $dbh = new \PDO('pgsql:dbname=xxx;host=xxx', 'xxx', 'xxx');
  $postgres_cache = new Cache\Pdo\Pgsql($dbh, $options);

  // with a SQL:1999 compliant DB, e.g. Oracle
  $dbh = new \PDO('oci:dbname=xxx', 'xxx', 'xxx');
  $sql1999_cache = new Cache\Pdo\Sql1999($dbh, $options);

The preflight option will create on-the-fly the required tables if these are mssing. Once these tables exist, set preflight to false in order to avoid the extraneous checks.

Filesystem specific

  // additional (default) options
  $options['directory'] = sys_get_temp_dir() . '/apix-cache'; // Directory where the cache is created
  $options['locking'] = true;                                 // File locking (recommended)
  
  $files_cache = new Cache\Files($options);
  // or
  $directory_cache = new Cache\Directory($options);  
  • Files: the cache metadata (expiration time and tags) are stored in the cache file directly.
  • Directory: the metadata are stored separately from the cached data.

Installation

This project adheres to Semantic Versioning and can be installed using composer:

$ composer require apix/cache:^1.3

All notable changes to this project are documented in its CHANGELOG.

License

This work is licensed under the New BSD license -- see the LICENSE for the full details.
Copyright (c) 2010-2016 Franck Cassedanne

cache's People

Contributors

alexpica avatar blaircooper avatar damianopetrungaro avatar davybatsalle avatar dimasikturbo avatar frqnck avatar great-antique avatar jspalink avatar macfja avatar mimmi20 avatar scrutinizer-auto-fixer avatar vaibhavpandeyvpz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cache's Issues

Support PHP 7.4

Feature Proposal

Description

Add PHP 7.4 to the Travis build and make any code changes necessary to run on PHP 7.4 (while continuing to support currently supported versions of PHP)

  • Apix-cache version: 1.3.x
  • Operating System: any
  • PHP Version: PHP 7.4, 7.3, 7.2, 7.1, 7.0, 5.6, 5.5, 5.4, & 5.3

Adding `increment` and `decrement` methods?

Do you have thoughts about adding a standard "increment" function for the AbstractCache.php in apix-cache? I know that both Redis and Memcached have this function, and its something I need at the moment -- using ->getAdapter()->... Instead.
Jonathan

Adding increment/decrement methods to AbstractCache.php would be useful indeed.

It would be good to have a base/inhertied implementations generic enough so that backends without dedicated functions would still benefit.

PDO, Runtime and Filesystem(s) don’t have dedicated (in|de)crementors — the rest do.

Essentially, a base implementations would be a two steps affair, i.e. retrieve and update/upsert a (numerical) value. The default (in|de)cremental value being 1.

Files cache not correctly handling EOL on Windows

Hello,

Whenever I try to read a cache file generated through Files on Windows, I get a miss with the following PHP notice:
PHP Notice: unserialize(): Error at offset 0 of 3224505 bytes in D:....\vendor\apix\cache\src\Files.php on line 70

I realized that Files::loadKey relies on the assumption that PHP_EOL (used for adding key and expiration to the cache entry) is of size 1, which is not the case on Windows (\r\n).
Just to check that it was indeed the issue, I changed 2 lines in Files::loadKey to have:
$pos+strlen(PHP_EOL)
instead of:
$pos+1

and the unserialize function returned correctly this time.
I'm not sure this is the only occurence of the issue.

Could it be possible to have a fix for this?

Best regards,

Davy

Uncaught Apix\Cache\PsrCache\InvalidArgumentException: Item key ('test:string') is invalid

Bug Report

Uncaught Apix\Cache\PsrCache\InvalidArgumentException: Item key ('test:string') is invalid

Code snippet

use Apix\Cache;

$backend = new \Redis();
$backend->connect('localhost');
$backend->select(1);
$cache = Cache\Factory::getPool($backend);

$item = $cache->getItem('test:string');

returns:

PHP Fatal error:  Uncaught Apix\Cache\PsrCache\InvalidArgumentException: Item key ('test:string') is invalid. in 
./vendor/apix/cache/src/PsrCache/Item.php:71
Stack trace:
#0 /vendor/apix/cache/src/PsrCache/Pool.php(53): Apix\Cache\PsrCache\Item::normalizedKey()
#1 /test_redis_apix.php(17): Apix\Cache\PsrCache\Pool->getItem()
#2 {main}
  thrown in /vendor/apix/cache/src/PsrCache/Item.php on line 71

But Redis allowed use this key:

root@quartz:/etc/redis# redis-cli --version
redis-cli 6.2.6

root@quartz:/etc/redis# redis-cli

127.0.0.1:6379> set test:string 'foobar'
OK
127.0.0.1:6379> get test:string
"foobar"
127.0.0.1:6379> 

Also, keys with : recommended by official documentation: https://redis.io/topics/data-types-intro#redis-keys

Very short keys are often not a good idea. There is little point in writing "u1000flw" as a key if you can instead write "user:1000:followers". The latter is more readable and the added space is minor compared to the space used by the key object itself and the value object. While short keys will obviously consume a bit less memory, your job is to find the right balance.

More details

  • Apix-cache version: 1.3
  • Operating System: LMDE (based debian 10)
  • PHP Version: 7.4
  • Redis 6.2.6

TaggablePool and Pool overrides prefix_key and prefix_tag options with hardcoded values

Hello,

I am looking at an issue when creating a pool using a factory, if I set the 'prefix_key' and 'prefix_tag' options they are overriden with hardcoded values: 'apix-key-' and 'apix-tag-'.

Apparently this happens in the constructors of TaggablePool and Pool. I would suggest to pass maybe just the 'taggable' boolean attribute to the adapters, and maybe not include the prefixes :)

Regards,
Alex

`Apix\Redis::flush()` use Redis KEYS

From Redis Documentation:

Warning: consider KEYS as a command that should only be used in production environments with extreme care. It may ruin performance when it is executed against large databases. This command is intended for debugging and special operations, such as changing your keyspace layout. Don't use KEYS in your regular application code. If you're looking for a way to find keys in a subset of your keyspace, consider using SCAN or sets.

The Redis module probably shouldn't be using the keys command - could probably be replaced with a private function that runs a scan on a pattern and compiles those lists.

'Files' and 'Directory' are not listed as clients in the Factory class

Hello,

Apparently the 'Files' and 'Directory' clients are not listed in the Factory, thus we cannot instantiate a factory by passing a string like 'files' or 'directory'. Also, the first argument in the implementation of those 2 classes should be an instance of the class itself, otherwise the factory will throw an error.

Maybe I missed something?!

Thanks,
Regards,
Alex

Please add support for APCu

Since APC as a caching engine is no longer supported, please add support for APCu. This could be as simple as cloning your APC class and renaming the methods to apcu_*

AbstractPdo::flush() drops the cache table on flush(true)

Bug Report

The implementation of the AbstractPdo classes drops the cache table on flush(true). This results on a exception being thrown if the cache is subsequently accessed as the cache table no longer exists.

Description

Additionally the implementation does not match the documentation for the method provided by Adapter::flush().

Code snippet

More details

  • Apix-cache version: 1.3.4
  • Operating System: RHEL 7.5, Windows 10
  • PHP Version: 7.2.14, 7.3.14
  • etc..

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.