PHPackages                             joby/smol-cache - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Caching](/categories/caching)
4. /
5. joby/smol-cache

ActiveLibrary[Caching](/categories/caching)

joby/smol-cache
===============

A set of simple lightweight caching implementations, and wrappers for implementing the same interfaces from common standards.

v1.2.0(5mo ago)01241MITPHPPHP &gt;=8.1CI passing

Since Jan 14Pushed 5mo agoCompare

[ Source](https://github.com/joby-lol/smol-cache)[ Packagist](https://packagist.org/packages/joby/smol-cache)[ RSS](/packages/joby-smol-cache/feed)WikiDiscussions main Synced 2w ago

READMEChangelog (5)Dependencies (2)Versions (6)Used By (1)

smolCache
=========

[](#smolcache)

A lightweight PHP caching library with tag support and hierarchical invalidation.

Installation
------------

[](#installation)

```
composer require joby-lol/smol-cache
```

About
-----

[](#about)

smol-cache provides a simple, consistent interface for caching data with support for tags, TTL expiration, and hierarchical cache invalidation. It includes two implementations:

- **EphemeralCache**: In-memory cache for single-request caching
- **SqliteCache**: Persistent SQLite-backed cache for multi-request caching

**Hierarchical Organization**: Both keys and tags use forward slash (`/`) as the canonical delimiter for hierarchical structures, enabling powerful recursive operations.

Basic Usage
-----------

[](#basic-usage)

```
use Joby\Smol\Cache\SqliteCache;

$cache = new SqliteCache('/path/to/cache.db', ttl: 3600);

// Set a value
$cache->set('user/123', ['name' => 'Alice', 'email' => 'alice@example.com']);

// Get a value
$user = $cache->get('user/123');

// Check if exists
if ($cache->has('user/123')) {
    // ...
}

// Delete a value
$cache->delete('user/123');
```

Cache Implementations
---------------------

[](#cache-implementations)

### EphemeralCache

[](#ephemeralcache)

In-memory cache that persists only for the current request.

```
use Joby\Smol\Cache\EphemeralCache;

$cache = new EphemeralCache(ttl: 30); // 30 second default TTL
```

### SqliteCache

[](#sqlitecache)

Persistent cache backed by SQLite database.

```
use Joby\Smol\Cache\SqliteCache;

// Basic usage
$cache = new SqliteCache('/path/to/cache.db', ttl: 300);

// With automatic cleanup (1 in 100 chance on each instantiation)
$cache = new SqliteCache('/path/to/cache.db', ttl: 300, cleanup_odds: 100);
```

Core Methods
------------

[](#core-methods)

### get()

[](#get)

Retrieve a value from the cache, optionally setting a default if not found.

```
// Simple get
$value = $cache->get('key');

// Get with default
$value = $cache->get('key', 'default value');

// Get with callable default (only executed if key doesn't exist)
$value = $cache->get('expensive/calculation', function() {
    return performExpensiveCalculation();
});

// Get with custom TTL and tags
$value = $cache->get('key', 'default', ttl: 600, tags: 'user-data');
```

### set()

[](#set)

Store a value in the cache.

```
// Simple set
$cache->set('key', 'value');

// Set with custom TTL
$cache->set('key', 'value', ttl: 1800);

// Set with tags
$cache->set('key', 'value', tags: ['user', 'profile']);

// Set with callable (executed immediately and result is cached)
$cache->set('key', fn() => computeValue());
```

### has()

[](#has)

Check if a key exists and is not expired.

```
if ($cache->has('user/123')) {
    // Key exists
}
```

### delete()

[](#delete)

Remove a value from the cache. Use slash (`/`) as the delimiter for hierarchical keys.

```
// Delete single key
$cache->delete('user/123');

// Delete recursively (deletes 'user' and all keys starting with 'user/123/')
$cache->delete('user', recursive: true);
// Deletes: user/123, user/123/profile, user/123/settings, user/123/posts/1, etc.
```

Tags
----

[](#tags)

Associate cache items with tags for grouped invalidation. Tags support the same hierarchical structure as keys using slash (`/`) delimiters.

```
// Set with single tag
$cache->set('user/123', $userData, tags: 'users');

// Set with multiple tags
$cache->set('post/456', $postData, tags: ['posts', 'user/123/content']);

// Clear all items with a tag
$cache->clear('users');
$cache->clear(['users', 'posts']);
```

### Hierarchical Tags

[](#hierarchical-tags)

Use slash (`/`) separated tag names for hierarchical invalidation.

```
$cache->set('post/1', $data, tags: 'content/posts/published');
$cache->set('post/2', $data, tags: 'content/posts/draft');
$cache->set('page/1', $data, tags: 'content/pages');

// Clear only published posts
$cache->clear('content/posts/published');

// Clear all posts (published and draft) - clears all tags starting with 'content/posts/'
$cache->clear('content/posts', recursive: true);

// Clear all content - clears all tags starting with 'content/'
$cache->clear('content', recursive: true);
```

Namespacing
-----------

[](#namespacing)

Create namespaced cache instances that automatically prefix keys with a namespace followed by a slash (`/`).

```
// Create namespaced cache
$userCache = $cache->namespace('user/123');

// Keys are automatically prefixed with 'user/123/'
$userCache->set('profile', $data);
// Actually sets 'user/123/profile'

$userCache->get('settings');
// Actually gets 'user/123/settings'
```

### Namespace with Default Tags and TTL

[](#namespace-with-default-tags-and-ttl)

```
// Namespace with tags that apply to all items
$userCache = $cache->namespace('user/123', tags: 'user-data', ttl: 600);

$userCache->set('profile', $data);
// Sets with both 'user-data' tag and 600 second TTL

// Clear all data for this user
$cache->clear('user-data');
```

### Nested Namespaces

[](#nested-namespaces)

Namespaces compose naturally with slash delimiters:

```
$userCache = $cache->namespace('user/123');
$settingsCache = $userCache->namespace('settings');

$settingsCache->set('theme', 'dark');
// Actually sets 'user/123/settings/theme'
```

Utility Methods
---------------

[](#utility-methods)

These are not included in the interface, but are available in the built-in implementations.

### flush()

[](#flush)

Delete all items from the cache.

```
$cache->flush();
```

### clean() (SqliteCache only)

[](#clean-sqlitecache-only)

Remove expired items from the database.

```
$cache->clean();
```

### compact() (SqliteCache only)

[](#compact-sqlitecache-only)

Reclaim unused space in the SQLite database. This operation is slow and locks the database.

```
$cache->compact();
```

Advanced Features
-----------------

[](#advanced-features)

### Callable Values and Defaults

[](#callable-values-and-defaults)

Both `get()` and `set()` accept callables, which are executed and their return value is cached.

```
// Get or compute and cache
$result = $cache->get('expensive/operation', doExpensiveOperation(...));

// Set with callable
$cache->set('timestamp', time(...));
```

### Complex Data Types

[](#complex-data-types)

All data is JSON-encoded internally, supporting arrays, objects, and scalar types. EphemeralCache does no manipulation of values, and supports literally anything that can be put in a PHP variable.

```
$cache->set('complex', [
    'user' => ['id' => 123, 'name' => 'Alice'],
    'metadata' => ['created' => time()],
    'flags' => ['active' => true, 'verified' => false]
]);

$data = $cache->get('complex');
// Returns the full array structure
```

### Hierarchical Keys

[](#hierarchical-keys)

Use slash (`/`) separators in keys for logical grouping with recursive deletion.

```
$cache->set('user/123/profile', $profile);
$cache->set('user/123/settings', $settings);
$cache->set('user/123/posts/1', $post1);
$cache->set('user/123/posts/2', $post2);

// Delete all user data - deletes all keys starting with 'user/123/'
$cache->delete('user/123', recursive: true);
```

Usage Patterns
--------------

[](#usage-patterns)

### Page Fragment Caching

[](#page-fragment-caching)

```
$cache = new SqliteCache('cache.db', ttl: 3600);

$content = $cache->get("page/$pageId/fragment/sidebar", function() use ($pageId) {
    return renderSidebar($pageId);
}, tags: "page/$pageId");

// Invalidate all fragments for a page
$cache->clear("page/$pageId");
```

### API Response Caching

[](#api-response-caching)

```
$apiCache = $cache->namespace('api/v1', ttl: 300);

$users = $apiCache->get("users/$userId", function() use ($userId) {
    return fetchUserFromDatabase($userId);
}, tags: ['users', "user/$userId"]);

// Invalidate all user data
$cache->clear('users');
```

### Computed Value Caching

[](#computed-value-caching)

```
$result = $cache->get('report/monthly', function() {
    return generateMonthlyReport();
}, ttl: 86400, tags: 'reports');

// Invalidate all reports
$cache->clear('reports');
```

Performance Considerations
--------------------------

[](#performance-considerations)

### SqliteCache Automatic Cleanup

[](#sqlitecache-automatic-cleanup)

Configure automatic cleanup to periodically remove expired entries:

```
// 1 in 100 chance of cleanup on each instantiation
$cache = new SqliteCache('cache.db', ttl: 3600, cleanup_odds: 100);
```

### Manual Cleanup

[](#manual-cleanup)

For cron-based cleanup:

```
$cache = new SqliteCache('cache.db');
$cache->clean();     // Remove expired items
$cache->compact();   // Reclaim disk space (optional, slow, locking)
```

Requirements
------------

[](#requirements)

Fully tested on PHP 8.3+, static analysis for PHP 8.1+.

License
-------

[](#license)

MIT License - See [LICENSE](LICENSE) file for details.

###  Health Score

36

—

LowBetter than 79% of packages

Maintenance69

Regular maintenance activity

Popularity12

Limited adoption so far

Community5

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~9 days

Total

5

Last Release

179d ago

PHP version history (2 changes)v1.0.0PHP &gt;=8.3

v1.1.1PHP &gt;=8.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/f4e606aa41ebfd7d82c365c6dc4ec158fb1b0bfff5f8dcbfad4ab53e3092e6a6?d=identicon)[jobyone](/maintainers/jobyone)

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/joby-smol-cache/health.svg)

```
[![Health](https://phpackages.com/badges/joby-smol-cache/health.svg)](https://phpackages.com/packages/joby-smol-cache)
```

###  Alternatives

[iazaran/smart-cache

Smart Cache is a caching optimization package designed to enhance the way your Laravel application handles data caching. It intelligently manages large data sets by compressing, chunking, or applying other optimization strategies to keep your application performant and efficient.

21114.2k](/packages/iazaran-smart-cache)[phpfastcache/phpssdb

PHP SSDB Driver for phpFastCache

14736.9k1](/packages/phpfastcache-phpssdb)[rapidwebltd/rw-file-cache

RW File Cache is a PHP File-based Caching Library. Its syntax is designed to closely resemble the PHP memcache extension.

15196.8k7](/packages/rapidwebltd-rw-file-cache)[yuzuru-s/redis-recommend

Wrapping Redis's sorted set APIs for specializing recommending operations.

392.9k](/packages/yuzuru-s-redis-recommend)[ichhabrecht/intcache

Turn uncachable page objects into cacheable links

193.9k](/packages/ichhabrecht-intcache)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
