schoolpalm/cache-store

A context-aware cache abstraction layer for Laravel applications with multi-tenant and multi-school support.

Maintainers

Package info

github.com/codeparl/cache-store

Issues

pkg:composer/schoolpalm/cache-store

Transparency log

Fund package maintenance!

Other

Statistics

Installs: 1

Dependents: 1

Suggesters: 1

Stars: 0

v1.0.0 2026-07-27 01:49 UTC

This package is auto-updated.

Last update: 2026-07-27 01:53:10 UTC


README

CacheStore Logo

CacheStore โ€” Context-Aware Cache for Laravel

Latest Version Total Downloads PHP Version License Tests

CacheStore is a powerful, context-aware cache abstraction layer for Laravel applications. It goes beyond simple key-value storage by introducing multi-tenant, multi-school, and custom context scoping โ€” making it ideal for SaaS platforms, school management systems, and any application that needs isolated cache namespaces.

Features

  • ๐Ÿข Context-Aware Caching โ€” Automatically scope cache keys by tenant, school, or custom context
  • ๐Ÿš€ Multiple Drivers โ€” Array, File, Database, Redis, and Laravel Cache drivers included
  • ๐Ÿ”Œ Pluggable Architecture โ€” Implement your own drivers via the CacheDriver contract
  • ๐Ÿ”„ Serialization โ€” Automatic PHP serialization for complex types (arrays, objects)
  • โšก Atomic Operations โ€” Increment/decrement bypass serialization for raw numeric operations
  • ๐Ÿงช Test-Ready โ€” Array driver for testing, trait-based test helpers
  • ๐Ÿ“ฆ Auto-Discovery โ€” Laravel package auto-discovery for service provider and facade

Quick Start

composer require schoolpalm/cache-store
use SchoolPalm\CacheStore\Facades\CacheStore;

// Basic usage
CacheStore::put('students_count', 500);
$count = CacheStore::get('students_count'); // 500

// Context-aware caching
CacheStore::forContext('tenant_abc', 'school_123')
    ->put('students', 500);

CacheStore::forContext('tenant_xyz', 'school_456')
    ->put('students', 900);

// Values are isolated per context!
CacheStore::forContext('tenant_abc', 'school_123')
    ->get('students'); // 500

CacheStore::forContext('tenant_xyz', 'school_456')
    ->get('students'); // 900

Table of Contents

Installation

You can install the package via Composer:

composer require schoolpalm/cache-store

Service Provider Discovery

Laravel will auto-discover the CacheStoreServiceProvider. If you have disabled package discovery, register it manually in config/app.php:

'providers' => [
    SchoolPalm\CacheStore\Providers\CacheStoreServiceProvider::class,
],

Facade

The CacheStore facade is also auto-discovered. If needed, register it manually:

'aliases' => [
    'CacheStore' => SchoolPalm\CacheStore\Facades\CacheStore::class,
],

Publishing Configuration

php artisan vendor:publish --provider="SchoolPalm\CacheStore\Providers\CacheStoreServiceProvider" --tag="config"

Configuration

The package configuration file config/cache-store.php is automatically merged with your application's config.

return [

    /*
    | Default cache driver used by CacheStore.
    */
    'driver' => env('CACHE_STORE_DRIVER', 'file'),

    /*
    | Separator used when building context-aware cache keys.
    | Example: tenant:school:key  or  tenant.school.key
    */
    'key_separator' => env('CACHE_STORE_KEY_SEPARATOR', ':'),

    /*
    | Prefix for all generated cache keys.
    | Example: schoolpalm:tenant:1:school:5:students
    */
    'prefix' => env('CACHE_STORE_PREFIX', 'schoolpalm'),

    /*
    | Context settings
    */
    'context' => [
        'tenant' => true,  // Include tenant identifier
        'school' => true,  // Include school identifier
    ],

    /*
    | Driver-specific configurations
    */
    'drivers' => [
        'file' => [
            'path' => storage_path('framework/cache'),
        ],
        'redis' => [
            'connection' => env('CACHE_STORE_REDIS_CONNECTION', 'default'),
        ],
        'database' => [
            'table' => 'cache_store',
        ],
    ],
];

Configuration Options

Option Type Default Description
driver string 'file' Default cache driver
key_separator string ':' Separator for context key segments
prefix string 'schoolpalm' Global prefix for all cache keys
context.tenant bool true Enable tenant context scoping
context.school bool true Enable school context scoping
drivers.file.path string storage_path('framework/cache') File cache storage path
drivers.redis.connection string 'default' Redis connection name
drivers.database.table string 'cache_store' Database cache table name

Usage

Basic Cache Operations

use SchoolPalm\CacheStore\Facades\CacheStore;

// Store a value
CacheStore::put('key', 'value', $ttl = 3600);

// Store a value permanently
CacheStore::forever('key', 'value');

// Retrieve a value
$value = CacheStore::get('key', $default = null);

// Check if key exists
if (CacheStore::has('key')) {
    // ...
}

// Store if not exists
CacheStore::add('key', 'value', $ttl = 3600);

// Retrieve and forget
$value = CacheStore::pull('key');

// Remove a value
CacheStore::forget('key');

// Increment / Decrement
CacheStore::increment('counter', 1);
CacheStore::decrement('counter', 1);

// Multiple values
CacheStore::putMany(['key1' => 'value1', 'key2' => 'value2']);
$values = CacheStore::many(['key1', 'key2']);

// Flush all cache
CacheStore::flush();

Complex Data Types

// Arrays
CacheStore::put('school', [
    'name' => 'Greenhill Academy',
    'students' => 1200,
    'teachers' => 80,
]);
$school = CacheStore::get('school');

// Objects
$user = (object) ['name' => 'John', 'role' => 'Admin'];
CacheStore::put('user', $user);
$retrieved = CacheStore::get('user'); // stdClass

Remember Pattern

// Cache the result of a callback
$value = CacheStore::remember('expensive_operation', 3600, function () {
    return someExpensiveOperation();
});

// Cache forever
$value = CacheStore::rememberForever('config', function () {
    return loadConfiguration();
});

Drivers

CacheStore ships with five built-in drivers, each optimized for different use cases:

Driver Class Backend Use Case
Array ArrayCacheDriver PHP memory Testing, local development
File FileCacheDriver File system Single-server, small apps
Database DatabaseCacheDriver SQL database Persistent, multi-server
Redis RedisCacheDriver Redis High-performance, distributed
Laravel LaravelCacheDriver Any Laravel store Bridge to existing cache

Using a Specific Driver

// At runtime via factory
$factory = app(\SchoolPalm\CacheStore\CacheDriverFactory::class);
$driver = $factory->driver('redis');
$driver->put('key', 'value');

// List available drivers
$drivers = $factory->available(); // ['array', 'file', 'database', 'redis', 'laravel']

// Check if a driver is available
if ($factory->has('redis')) {
    // ...
}

Writing a Custom Driver

Implement the CacheDriver contract to create your own driver:

use SchoolPalm\CacheStore\Contracts\CacheDriver;

class MongoCacheDriver implements CacheDriver
{
    // Implement all CacheDriver methods...
}

// Register it in the factory
$factory->extend('mongo', function () {
    return new MongoCacheDriver();
});

Context-Aware Caching

The standout feature of CacheStore is context-aware caching โ€” automatically scoping cache keys by tenant, school, or any custom context.

How It Works

When you use a context, CacheStore prefixes your cache keys with context identifiers:

schoolpalm:tenant_abc:school_123:students

This ensures that the same key name in different contexts never collides.

Usage

// Store in a specific context
CacheStore::forContext('tenant_abc', 'school_123')
    ->put('students_count', 500);

// Retrieve from the same context
CacheStore::forContext('tenant_abc', 'school_123')
    ->get('students_count'); // 500

// Different context โ€” isolated value
CacheStore::forContext('tenant_xyz', 'school_456')
    ->get('students_count'); // null

Configuring Context

You can enable/disable context segments in the config:

'context' => [
    'tenant' => true,  // Include tenant in key
    'school' => true,  // Include school in key
],

When disabled, the corresponding context segment is omitted from the cache key.

Key Building Logic

The cache key is built using the following pattern:

{prefix}:{tenant}:{school}:{key}

Where:

  • {prefix} โ€” Global prefix from config (schoolpalm)
  • {tenant} โ€” Tenant identifier (if context.tenant is enabled)
  • {school} โ€” School identifier (if context.school is enabled)
  • {key} โ€” Your cache key
  • Segments are joined using the configured key_separator

Testing

CacheStore makes testing a breeze with its Array driver and shared test traits.

Running Tests

composer test

Test Traits

Use the CacheDriverBehaviour trait to run a comprehensive test suite against any driver:

use SchoolPalm\CacheStore\Drivers\ArrayCacheDriver;
use SchoolPalm\CacheStore\Tests\Concerns\CacheDriverBehaviour;

uses(CacheDriverBehaviour::class);

beforeEach(function () {
    $this->driver = new ArrayCacheDriver(
        app(\Illuminate\Contracts\Cache\Repository::class),
        app(\SchoolPalm\CacheStore\Support\CacheSerializer::class)
    );
});

This automatically tests:

  • Store & retrieve values
  • Store & retrieve integer values
  • Return default value for missing keys
  • Key existence checks
  • Overwrite existing values
  • Forget operations
  • Array storage
  • Object storage
  • Boolean storage
  • Forever storage
  • Add (unique key) operations
  • Pull operations
  • Pull returns default for missing keys
  • Increment / Decrement
  • Many operations
  • Many returns null for missing keys
  • Flush operations

Creating a Custom Driver Test

use SchoolPalm\CacheStore\Drivers\YourDriver;
use SchoolPalm\CacheStore\Tests\Concerns\CacheDriverBehaviour;
use SchoolPalm\CacheStore\Tests\Support\CreatesCacheDrivers;

uses(
    CreatesCacheDrivers::class,
    CacheDriverBehaviour::class
);

beforeEach(function () {
    $this->driver = $this->makeDriver(
        YourDriver::class
    );
});

Note: Include tests/Support/cacheDriverTests.php in your test file to execute the shared test suite.

Driver Contract

All cache drivers must implement the SchoolPalm\CacheStore\Contracts\CacheDriver interface:

namespace SchoolPalm\CacheStore\Contracts;

interface CacheDriver
{
    public function get(string $key, mixed $default = null): mixed;
    public function put(string $key, mixed $value, DateTimeInterface|DateInterval|int|null $ttl = null): bool;
    public function forever(string $key, mixed $value): bool;
    public function add(string $key, mixed $value, DateTimeInterface|DateInterval|int|null $ttl = null): bool;
    public function has(string $key): bool;
    public function forget(string $key): bool;
    public function flush(): bool;
    public function increment(string $key, int $value = 1): int;
    public function decrement(string $key, int $value = 1): int;
    public function pull(string $key, mixed $default = null): mixed;
    public function many(array $keys): array;
    public function putMany(array $values, DateTimeInterface|DateInterval|int|null $ttl = null): bool;
}

Serialization Behavior

Drivers handle serialization automatically via CacheSerializer:

Value Type Storage Format Retrieval
string Stored as-is Returned as string
int Stored as string Cast back to int
float Stored as string Cast back to float
bool PHP serialized (b:1; / b:0;) Unserialized to bool
array PHP serialized Unserialized to array
object PHP serialized Unserialized to original class
null Not stored Default value returned

Note: increment() and decrement() bypass serialization for raw numeric operations at the storage layer.

Requirements

  • PHP: ^8.2
  • Laravel: ^12.0 (Illuminate\Support and Illuminate\Cache)
  • Database Driver: Requires a database connection when using the database cache driver
  • Redis Driver: Requires predis/predis or phpredis extension when using the redis cache driver

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Development Setup

  1. Clone the repository
  2. Run composer install
  3. Run composer build to set up the testbench workbench
  4. Run composer test to execute tests

Code Style

This package follows the PSR-12 coding standard.

Security

Please see SECURITY for our security policy.

Credits

License

The MIT License (MIT). Please see License File for more information.

Built with โค๏ธ by SchoolPalm for the Laravel community