PHP code example of hiblaphp / cache

1. Go to this page and download the library: Download hiblaphp/cache library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

hiblaphp / cache example snippets


use Hibla\Cache\ArrayCache;
use function Hibla\await;

$cache = new ArrayCache();

// Store a value
await($cache->set('user:1', $user));

// Retrieve a value — resolves with $default on cache miss
$user = await($cache->get('user:1'));

// Delete a value
await($cache->delete('user:1'));

// Clear all values
await($cache->clear());

async(function () use ($cache) {
    $user = await($cache->get('user:1'));

    if ($user === null) {
        $user = await(fetchUserFromDatabase(1));
        await($cache->set('user:1', $user, ttl: 300));
    }

    return $user;
});

// Expire after 5 minutes
await($cache->set('session:abc', $session, 300));

// Expire after 500 milliseconds
await($cache->set('rate-limit:user:1', 1, 0.5));

// Expire after 1.5 seconds
await($cache->set('lock:resource', true, 1.5));

// Expire after 1 hour
await($cache->set('report:daily', $report, new DateInterval('PT1H')));

// Expire after 7 days
await($cache->set('token:refresh', $token, new DateInterval('P7D')));

// Expire after 30 minutes
await($cache->set('session:tmp', $data, new DateInterval('PT30M')));

// Hold at most 1000 items
$cache = new ArrayCache(limit: 1000);

// Unlimited — default
$cache = new ArrayCache();

$cache = new ArrayCache(limit: 0);  // throws InvalidArgumentException
$cache = new ArrayCache(limit: -1); // throws InvalidArgumentException

$cache = new ArrayCache(limit: 3);

await($cache->set('a', 1));
await($cache->set('b', 2, ttl: 0.001)); // expires almost immediately
await($cache->set('c', 3));

usleep(2000); // let 'b' expire

// Adding a fourth item — 'b' is evicted first because it is expired,
// even though 'a' is the least recently used live item
await($cache->set('d', 4));

$b = await($cache->get('b')); // null — evicted
$a = await($cache->get('a')); // 1 — still present

$cache = new ArrayCache(limit: 100, onEvict: function (string $key, mixed $value) {
    if ($value instanceof ResourceInterface) {
        $value->close();
    }
});

$results = await($cache->getMultiple(['user:1', 'user:2', 'user:3']));

// $results = [
//   'user:1' => $user1,   // found
//   'user:2' => null,     // not found — default
//   'user:3' => $user3,   // found
// ]

$results = await($cache->getMultiple(['config:a', 'config:b'], default: []));

await($cache->setMultiple([
    'user:1' => $user1,
    'user:2' => $user2,
    'user:3' => $user3,
], ttl: 300));

await($cache->deleteMultiple(['user:1', 'user:2', 'user:3']));

$exists = await($cache->has('user:1')); // true or false

if (await($cache->has('user:1'))) {       // LRU order unchanged
    $user = await($cache->get('user:1')); // LRU order updated here
}

use function Hibla\async;
use function Hibla\await;

async(function () use ($cache, $userId) {
    // Cache-aside pattern — check cache, fall back to source
    $user = await($cache->get("user:$userId"));

    if ($user === null) {
        $user = await(Http::get("/users/$userId"));
        await($cache->set("user:$userId", $user, ttl: 60));
    }

    return $user;
});

use Hibla\Promise\Promise;
use function Hibla\await;

// Warm multiple cache entries concurrently
await(Promise::all([
    $cache->set('user:1', $user1, 300),
    $cache->set('user:2', $user2, 300),
    $cache->set('user:3', $user3, 300),
]));

// Read multiple keys concurrently alongside other async work
[$cached, $liveConfig] = await(Promise::all([
    $cache->get('user:1'),
    Http::get('/config'),
]));

$promise = $cache->get('user:1');
// By this line, the array has already been read and the promise is
// already fulfilled. Calling cancel() on it is a no-op — the work
// is done.
$promise->cancel(); // no-op — isFulfilled() is already true

public function get(string $key, mixed $default = null): PromiseInterface
{
    $promise   = new Promise();
    $requestId = $this->redis->get($key, function (?string $value) use ($promise, $default) {
        $promise->resolve($value !== null ? unserialize($value) : $default);
    });

    // Real async work — cancellation can actually stop something
    $promise->onCancel(function () use ($requestId) {
        $this->redis->cancel($requestId);
    });

    return $promise;
}

use Hibla\Cache\Interfaces\CacheInterface;

class UserRepository
{
    public function __construct(private CacheInterface $cache) {}

    public function find(int $id): PromiseInterface
    {
        return async(function () use ($id) {
            $cached = await($this->cache->get("user:$id"));

            if ($cached !== null) {
                return $cached;
            }

            $user = await($this->db->query("SELECT * FROM users WHERE id = ?", $id));
            await($this->cache->set("user:$id", $user, ttl: 300));

            return $user;
        });
    }
}

// Use ArrayCache in development, swap to RedisCache in production —
// UserRepository does not change
$repo = new UserRepository(new ArrayCache(limit: 500));

use Hibla\Cache\Interfaces\CacheInterface;
use Hibla\Promise\Interfaces\PromiseInterface;
use Hibla\Promise\Promise;

class RedisCache implements CacheInterface
{
    public function get(string $key, mixed $default = null): PromiseInterface
    {
        $promise   = new Promise();
        $requestId = $this->redis->get($key, function (?string $value) use ($promise, $default) {
            $promise->resolve($value !== null ? unserialize($value) : $default);
        });

        $promise->onCancel(function () use ($requestId) {
            $this->redis->cancel($requestId);
        });

        return $promise;
    }

    // ... implement remaining methods
}