tlmcclatchey / registry
A tiny, DI-friendly in-memory registry with per-key locks and a global freeze switch.
Requires
- php: ^8.4
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.50
- phpstan/phpstan: ^1.11
- phpunit/phpunit: ^11.0
This package is auto-updated.
Last update: 2026-03-15 21:03:30 UTC
README
A tiny, dependency-injection-friendly in-memory registry with per-key locks and a global freeze switch.
Designed as a safer alternative to ad-hoc globals for configuration, runtime state, and bootstrapping data in PHP applications.
Features
- Simple in-memory key/value storage
- Per-key lock flags to prevent specific mutations
- Global freeze to make the registry fully read-only after boot
- Clean interface for DI containers and frameworks
- Zero dependencies, tiny footprint
Installation
composer require tlmcclatchey/registry
Requires PHP 8.4+.
Quick Start
use TLMcClatchey\Registry\MemoryRegistry; $registry = new MemoryRegistry(); // define keys $registry->define('config', array: true); $registry->assign('config', 'env', 'prod'); // set scalar value $registry->set('debug', false); // freeze registry after boot $registry->freeze(); // reads still work $env = $registry->get('config')['env'];
After calling freeze(), all mutation operations throw.
Core Concepts
1. Keys
A key may contain:
- scalar value (
int|string|bool|float|null) - array value (for map/list-style storage)
$registry->set('version', '1.0.0'); $registry->define('services', array: true);
2. Assigning Array Values
$registry->assign('services', 'cache', 'redis'); $registry->assign('services', 'queue', 'sqs');
Check existence:
$registry->isAssigned('services', 'cache'); // true
3. Lock Flags
Each key can prevent specific mutations.
| Flag | Prevents |
|---|---|
NO_SET |
overwriting the whole value |
NO_APPEND |
appending to arrays |
NO_PREPEND |
prepending to arrays |
NO_ASSIGN |
assigning subkeys |
NO_UNASSIGN |
removing subkeys |
NO_CLEAR |
removing the key entirely |
Convenience presets:
RegistryLocks::READONLY RegistryLocks::READ_MODIFY
Example:
use TLMcClatchey\Registry\RegistryLocks; $registry->define('config', lock: RegistryLocks::READONLY, array: true); // any mutation now throws RegistryException
4. Global Freeze
Freeze the entire registry once bootstrapping is complete:
$registry->freeze();
After freezing:
- All mutation methods throw
RegistryException - Read operations continue working
Perfect for:
- application boot phases
- compiled container configs
- immutable runtime state
API Overview
Read
$registry->get(string $key, mixed $default = null); $registry->has(string $key); $registry->all(); $registry->keys();
Write
$registry->define(string $key, int $lock = 0, bool $array = false); $registry->set(string $key, mixed $value, int $lock = 0); $registry->clear(string $key);
Array Operations
$registry->assign(string $key, string $subkey, scalar|null $value); $registry->unassign(string $key, string $subkey); $registry->prepend(string $key, scalar|null $value); $registry->append(string $key, scalar|null $value);
Lifecycle
$registry->freeze(); $registry->isFrozen();
When to Use This
Good fit:
- boot configuration storage
- DI container build phase
- runtime feature flags
- small framework kernels
- CLI app state
Not intended for:
- persistence
- cross-request storage
- caching layers
- large datasets
Philosophy
This library exists for one reason:
Sometimes you do need global state. You just don’t need chaos.
So instead of banning globals, this gives you:
- rules
- immutability after boot
- predictable failure
Like a registry… but with adult supervision.
License
See the LICENSE.md file for full details.