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

Memory Laravel Package

orchestra/memory

Orchestra Memory gives Laravel apps a lightweight in-memory key-value store for the current request lifecycle. Use its simple put, get, has, and forget API to cache computed values and share state between components without touching persistent storage or external cache drivers.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and confirm the wiring. Require orchestra/memory:^6.0 (Laravel 8 floor — check composer.json in the repo directly rather than trusting the release note). The package ships a MemoryServiceProvider and a Memory facade; confirm both are registered under extra.laravel.providers / extra.laravel.aliases before writing any code, since a missing facade alias is the most common first-run failure.

Read the drivers before you read anything else. The entire package is small — a manager, a facade, a repository interface, and a handful of drivers (array/runtime, cache, database/eloquent). Spend twenty minutes on the driver classes rather than the README. Your day-to-day behaviour is entirely determined by which driver you pick: what serialization happens, whether reads hit storage every time, and what survives a process restart.

Publish or hand-roll the config. If the repo ships a publishable config, publish it and set the default driver and namespace there. If it doesn't, create the config yourself — either way, keep driver choice in config, never in call sites, so tests and staging can differ from production without a code change.

First use case: one admin-editable value. Pick a single setting that genuinely needs to change without a deploy — a support email, a maintenance banner, a feature toggle. Wire it end to end:

use Orchestra\Memory\Facades\Memory;

// Write (an admin controller / artisan command)
Memory::make('app')->put('support_email', '[email protected]');

// Read (anywhere in the request lifecycle)
$email = Memory::make('app')->get('support_email', config('mail.support'));

Verify the round trip with the array driver in a test before you ever touch the database driver. If the array driver works and the database driver doesn't, the problem is your schema or connection — not your application code.

Database driver = you own the migration. Do not assume a migration is shipped. Check the repo for a schema stub; if there isn't one, you are creating the settings table yourself and you should do it deliberately, with a unique index on the namespace/key pair.

Implementation Patterns

Wrap it once, then never call the facade again. The highest-value thing you can do on day one is a thin Settings class that owns every Memory::make() call. The package API takes namespace and key as raw strings, which means a typo produces a silent empty result rather than an exception. One wrapper gives you constants for namespaces, a single place to add casting, and — critically — a single file to rewrite if you ever replace the package.

Namespace by scope, not by data type. Use global, tenant:{id}, extension:{vendor/package} as namespaces. This is where the package actually earns its keep: per-tenant overrides layered over global defaults becomes a read order in one method rather than three bespoke implementations.

public function get(string $key, $default = null, ?string $scope = null)
{
    return Memory::make($scope ?? 'global')->get($key)
        ?? Memory::make('global')->get($key, $default);
}

Hydrate config at boot — carefully. The most tempting pattern is merging memory values into config() inside a service provider so the rest of the app can keep using config(). It works, but it runs once per process, which means under Octane it runs once per worker, and a settings change made by an admin won't be visible until workers recycle. If you do this, pair it with a cache TTL or an explicit reload path, and document the staleness window for ops.

Choose the driver per environment, not per feature. Array/runtime in tests (fast, isolated, no cleanup), cache in staging, database in production for anything authoritative. Write the code so the driver is the only thing that changes.

Build a small schema on top. The package stores values; it does not know types, defaults, or validation. Define your own array of key => ['default' => ..., 'cast' => 'bool', 'rules' => ...] and loop over it in the settings controller. This is twenty lines and it is what turns a key-value store into a usable admin panel.

Testing. Bind the array driver in phpunit.xml or the test case base class and reset it in setUp(). If you're on the database driver in tests, use RefreshDatabase — but don't, because settings written in one test will leak into the next and produce failures that look like ordering bugs.

Gotchas and Tips

Serialization round-trips bite. Check whether the driver JSON-encodes values. The classic bug is put('flag', true) returning the string "1" or "true" on read. === false checks then silently never match. Verify with a var_dump on each driver you use and cast at the wrapper boundary.

Distinguish "missing" from "null". get($key, $default) typically only returns the default on a genuine miss. If you store null deliberately, get() may hand it back instead of your default — use has() when the difference matters.

The cache driver is not durable. A php artisan cache:clear, a Redis eviction under memory pressure, or a key-prefix change silently deletes every setting. Never put the only copy of anything authoritative there. The database driver is the one to use for settings an admin typed in.

The array/runtime driver under Octane is a trap. Per-process state in a long-lived worker persists across requests. In a normal PHP-FPM setup that driver is safely request-scoped; under Octane it is shared memory. Do not use it in an Octane deployment for anything user-specific, and be suspicious of it in tests that assert isolation.

Watch the query count on the database driver. If reads aren't memoized, a settings-heavy page issues one query per get(). Load the whole namespace once per request (all() or equivalent, if the driver exposes it) and read from the local array.

Debug by dumping the namespace, not the key. When a value "isn't saving," the cause is usually the wrong namespace, a silently failed write, or a different driver than you assumed. Dump the full contents of the namespace and inspect the cache key prefix or the table rows directly before you touch application code.

Keep your usage shallow. With effectively zero dependents, you own the upgrade path and the debugging. Pin the exact version, never subclass package internals, and treat your Settings wrapper as the real public API — the package should be replaceable in an afternoon. That is the only thing that makes the bus-factor acceptable.

Verify the Octane claim yourself if you're on Octane. "Added support for Laravel Octane" is a statement about request-state isolation. Exercise your settings paths under concurrent load; the failure mode is intermittent cross-request bleed, which a smoke test will not catch.

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.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource