Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Array Cache Laravel Package

smorken/array-cache

A lightweight in-memory array cache driver for Laravel. Store and retrieve cached values in a simple PHP array, ideal for testing, per-request caching, and avoiding external cache backends during development.

View on GitHub
Deep Wiki
Context7

Getting Started

smorken/array-cache is an in-memory array cache for PHP and Laravel — effectively a place to stash values for the life of a single request/job without touching Redis, Memcached, or the filesystem. Treat it as a memoization layer, not as a real cache backend.

It is not published on Packagist, so register the VCS repository first:

composer config repositories.array-cache vcs https://bitbucket.org/scott_morken/array-cache.git
composer require smorken/array-cache

Bitbucket is private by default, so Composer needs credentials — an SSH key or an access token (composer config -g bitbucket-oauth...) — both locally and in CI.

Where to look first:

  1. The service provider (src/*ServiceProvider.php) — confirms whether it registers a cache driver alias (e.g. array, arraycache) or just binds a singleton class. This single file tells you whether you use it as Cache::store('...') or as an injected object.
  2. The store/manager class — check which PSR-16 / Illuminate\Contracts\Cache\Repository methods are actually implemented (get, put, remember, has, forget, flush, tags, TTL handling).
  3. Any published config — php artisan vendor:publish to see defaults (prefix, TTL fallback).

First use case — deduplicating identical work inside one request:

$settings = Cache::store('array')->remember(
    'settings.all',
    now()->addMinutes(5),
    fn () => Setting::query()->pluck('value', 'key')->all()
);

Because the value lives only for the current process, the TTL is largely decorative; the win is that the closure runs once instead of N times when several services ask for the same thing.

Implementation Patterns

Repository decorator (the highest-value pattern). Wrap a slow repository and put the array cache in front of it. This keeps the caching concern out of controllers and makes the lifetime of the memo explicit:

final class CachedUserRepository implements UserRepository
{
    public function __construct(
        private UserRepository $inner,
        private Repository $cache,
    ) {}

    public function find(int $id): ?User
    {
        return $this->cache->remember(
            "users.{$id}",
            now()->addHour(),
            fn () => $this->inner->find($id)
        );
    }
}

Two-tier cache (array → Redis). Check the cheap store first, fall through to the persistent one, and hydrate the array so the second read in the same request is free:

function cached(string $key, Closure $callback)
{
    $local = Cache::store('array');

    if ($local->has($key)) {
        return $local->get($key);
    }

    return $local->put($key, Cache::remember($key, 3600, $callback));
}

Per-request context object. Store the authenticated user's resolved permissions, tenant configuration, feature flags, or a formatted nav tree once and read it from every Blade partial and policy. This is where array caching normally removes the most queries.

Request-scoped injection. Register the store as a singleton in a service provider and inject Repository into services rather than calling the Cache facade statically — it makes swapping in a fake trivial.

Test isolation. Use it to make test suites fast: bind the array store as the default cache in the test case so nothing persists between tests, and reset it in setUp/tearDown (flush() if supported, otherwise re-instantiate the singleton via $this->app->forgetInstance(...)).

Warm it deliberately. In queue jobs and console commands that iterate over many models, prime the array cache in a loop before the hot path — e.g. Model::all()->each(fn ($m) => $cache->put("m.{$m->id}", $m)) — then let the loop body hit the cache instead of the DB.

Bust on write. Whenever you write through the decorator, forget() the corresponding key (and any list/index keys that would contain the changed row); there are no tags to fall back on unless the package implements them.

Gotchas and Tips

  • It does not survive the request. Nothing is shared between HTTP requests, queue jobs, or CLI commands. If you need cross-request persistence this is the wrong tool — use Redis or the database cache.
  • Octane and long-running workers are the real hazard. Under Laravel Octane, Swoole/RoadRunner workers are reused, so a "request-scoped" array becomes a cross-request leak: stale users, wrong tenant data, permission bleed. Flush the store in a middleware terminate() or an Octane RequestReceived/RequestTerminated listener, or bind it as a scoped (not singleton) instance.
  • Never use it for locks, rate limits, or counters. There is no atomicity and no sharing between processes; Cache::lock() semantics will not hold.
  • Unbounded growth. A naive array store keeps every key you write for the process lifetime. In a job processing 500k rows, keying per-row will exhaust memory. Chunk and flush, or cap the entries.
  • TTL is cosmetic in-process. Don't rely on expiry for correctness — expiry only matters if the process happens to outlive the TTL.
  • Null vs. miss. Check how the package distinguishes a cached null from a miss (has() may be implemented as isset()); if it conflates them, your "remember" closures will re-run on every access for nullable results.
  • Cache key collisions across tests. Without a prefix, keys like users.1 bleed between test methods if the container is reused. Set a prefix per test or flush in setUp.
  • Composer/auth friction. Because it's a Bitbucket VCS package, CI images without credentials fail at composer install. Vendor it, mirror it to a private Satis/Composer repository, or bake the token into the build secret store.
  • Abandonment risk. Zero stars, zero dependents, private host — pin an exact commit ("dev-master#abcdef1") in composer.json and vendor the source, because a force-push or deleted repo breaks your build. Realistically, the Laravel array cache driver plus a small singleton binding reproduces this package's behaviour in ~20 lines, which is worth weighing before you take the dependency.
  • Extension points to confirm before relying on them: tags (->tags([...]) throws on stores that don't support them), flush(), increment/decrement, and rememberForever. Check the implementation — a thin array wrapper often implements only get/put/has/forget and will blow up on the rest.
  • Debugging tip: if values appear to change mid-request, something is writing through the decorator without busting — log every put/forget on the array store in local development; the trail is short because the store is empty at the start of every request.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource