Tired of spinning up a DB for small tools? You can persist PHP objects to disk with lazy loading, TTLs, and safe writes using melia/object-storage. It’s fast to adopt, crash-safe, and keeps memory low.
What it is
- File-backed storage for PHP objects
- UUID-based references and lazy loading
- Per-object TTL/expiration
- Atomic writes and locking
- Class stubs for fast listing by class
- Optional in-memory cache
When to use
- CLIs, daemons, small web apps, plugins
- Prototypes or self-hosted tools with a writable directory
- Complex object graphs without a full database
When not to
- You need queries/joins across large datasets
- Multi-host concurrent writes without a distributed lock
Quickstart
Install
composer require melia/object-storage
Store and load
<?php
use melia∖ObjectStorage∖ObjectStorage;
$storage = new ObjectStorage(__DIR__ . '/var/object-store');
$note = (object)['title' => 'Hello', 'body' => 'World'];
$uuid = $storage->store($note);
$loaded = $storage->load($uuid);
echo $loaded->title; // Hello
Lazy references
<?php
$owner = (object)['email' => 'owner@example.com'];
$ownerId = $storage->store($owner);
$team = (object)['name' => 'Team', 'owner' => $owner];
$teamId = $storage->store($team);
$loaded = $storage->load($teamId);
$ownerObj = $loaded->owner->getObject(); // resolved on access
TTL and expiration
<?php
$session = (object)['user' => 'alice'];
$id = $storage->store($session, ttl: 60); // 60s
$storage->setExpiration($id, new DateTimeImmutable('+10 minutes'));
List by class
<?php
foreach ($storage->list(Some∖ClassName::class) as $uuid) {
// handle UUIDs of that class
}
Searching objects
<?php
foreach ($storage->match(function (object $object) {
return true;
}) as $uuid => $object) {
// handle UUIDs of that class
}
How it works
- Graphs become JSON + metadata with UUID pointers
- Lazy references load only when needed
- Atomic writes + locks reduce corruption
- Checksums avoid unnecessary rewrites
Practical tips
- Use a fast, writable storage directory
- Run a periodic GC for expired objects
- Single host by default; add a distributed lock for multi-host
- Inject a PSR-16 cache for hot objects
Takeaway For small and embedded PHP apps, file-backed object storage with lazy refs and TTLs can replace a database. Install, store, load—done.
Top comments (4)
I see you put a lot of effort in the library.
I'm wondering if you have considered SQLite as an option, before starting the library?
I can understand you don't want a Postgresql or a Redis or a MongoDB.
SQLite is just one file, with all the benefits that come with using SQL.
Hello david,
thank you for taking your time writing a feedback.
Yes i thought about using SQLLite too. But the main idea behind my library is to store / load any object without creating a schema or care about hydration.
I know my library is risky for schema drifts and indxing is also not supported.
But i think this can be solved somehow in future.
I also wanted to challenge me and see what is possible. Maybe some developers like to use it for their prototypes or something else.
I just like to share what i have done, since i think the code quality is decent and the library itself useful.
Best regards
Elia
I understand you want to challenge yourself, and you are proud of your accomplishment.
I just see more potential problems with files than with sqlite.
Thats partially true. When you think about databases and solid libraries. All started from scratch. They have been improved over time. I want this for my library too.
You would be right to say, you should consider using it for production. This of course i would not recommend too since its in an early stage and needs more tests and hardening.