Stash

Stash makes it easy to speed up your code by caching the results of expensive functions or code. Certain actions, like database queries or calls to external APIs, take a lot of time to run but tend to have the same results over short periods of time. This makes it much more efficient to store the results and call them back up later.

Features

PSR-6 Support
Stash impliments the PSR-6 interfaces, allowing Stash to be injected into any library that supports PSR-6.
Regeneration Before Expiration
Stash gives developers the option to regenerate a cached item before it misses, making sure that up to data is always available while limiting expensive code to running one instance at a time.
Distributed Cache Misses
In order to reduce sudden spikes on a system Stash alters the expiration times by lowering the cache age a random amount, thus distributing the cache hits over a period of time.
Hierarchal Cache
Stored items can be nested, like the folders of a filesystem. This allows for related items to be groups together and erased when changed. Storing a user's basic information can be nested 'users/userId/info', allow all of the user's information to be removed quite easily.
Interchangeable Back Ends
Stash can use a number of different storage engines to persist cache items between requests. Current drivers include Filesystem, APC, Memcached, and Sqlite drivers.
Composite Drivers
It occasionally makes sense to use multiple backends- for example, you may have a small amount of memory to allot but a large piece of filesystem, in which case using APC and the FileSystem driver together is an ideal solution. Stash allows you to do this using the special backend, MultiDriver, which can take an unlimited number of drivers.
Stampede Protection
When a particularly expensive to generate item misses it can cause a chain reaction- the system slows down as it generates the cache, but the longer it takes the more processes that miss and start regenerating it. Stash gives the developer the ability to limit cache regeneration to a single process, as well as an assortment of ways to handle misses.
Stores all PHP Datatypes
Stash can store all of the php native datatypes- integers, booleans, null, strings, arrays and objects that can be serialized.
Optimized Data Encoding
Care is taken to use the fastest possible encoding and decoding functions when storing data, with the preference being to store things in their native data type. Serialization is reserved only for objects or deep multidimensional arrays where breaking down each component individually would be too long.
Comprehensively Unit Tested
Every driver, class and wrapper is extensively tested. This includes using a variety of datatypes and ranges in order to ensure that the data you put in is the data you get out.

Example Usage

Stash functions as a key-value store: you place things into the cache using a key and you retrieve them using the same key.

<?php
$item = $pool->getItem('fruit');
$pool->save($item->set('apple'))

var_dump($item->get());
// string(5) "apple"

This works between requests as well.

<?php
// First Request
$item = $pool->getItem('fruit');
$pool->save($item->set('apple'))

// Second Request
$item = $pool->getItem('fruit');
var_dump($item->get());
// string(5) "apple"

Putting this together with the rest of Stash allows for a simple yet flexible way to speed up scripts by reusing data.

<?php
function getUserInfo($userId)
{
    $pool = $this->cachePool;

    // Get a Stash object from the cache pool.
    $item = $pool->getItem("/user/{$userId}/info");

    // Get the data from it, if any happens to be there.
    $userInfo = $item->get();

    // Check to see if the cache missed, which could mean that it either
    // didn't exist or was stale.
    if($item->isMiss())
    {
        // Run the relatively expensive code.
        $userInfo = loadUserInfoFromDatabase($userId);

        // Set the new value in $item.
        $item->set($userInfo);

        // Store the expensive code so the next time it doesn't miss.
        $pool->save($item)
    }

    return $userInfo;
}

function saveUserInfo($userId, $infoArray)
{
    // Save the data- dumped behind a function just for the example.
    saveDataToDatabase($userId, $infoArray);

    // Clear out the now invalid data from the cache.
    $this->cachePool->clear('user', $userId, 'info');
}

For an in-depth look at using Stash take a look at Basic Usage and Drivers.

License

Stash is licensed under the New BSD License. This means you are free to use it in any of your projects, proprietary or open source. While you aren't obligated to contribute back, any bug fixes or enhancements are appreciated -- besides, getting your code into the main branch is so much easier than maintaining your own fork.