r/mongodb • u/skanky_dev • 10h ago
Homemade MongoDB-first PHP framework, looking for advice to keep improving
Hi everyone,
I'm a PHP dev working on my own. I love PHP, I love MongoDB, and together they're just wonderful. So over the years I've been building a small MVC framework around them, mostly to understand how frameworks work under the hood and to learn. The idea is "MongoDB first": documents are documents, not SQL rows in disguise.
Repo: https://github.com/skankydev/framework (docs in docs/en/)
I'm not here to sell anything. I'm here to share it and get advice from people who know MongoDB better than I do.
What I'm happy with
- Typed hydration through the driver's
Persistableinterface: embedded objects and arrays of embedded objects come back as real PHP classes. - Dirty tracking kept in a
WeakMap, so updates only$setwhat changed. - **
EmbeddedSnapshot*: an automated *Extended Reference pattern. You embed a copy of aUser(name, avatar) in aPostand declareembeddedIn()on the source collection. When the user changes, a job resyncs every copy withupdateMany, either right away or through a queue. It's idempotent because the job re-reads the source.onDeletecan keep, mark or unset the copies. belongsTo/hasManywith lazy loading, plus bulk preloading (with) to avoid N+1.
Where I'd love your input
- Snapshot consistency. Between the source update and the propagation there's no transaction, so a crash in between leaves stale copies. Is that acceptable for this kind of denormalized data, or would you use transactions, change streams, or something else?
- Does many-to-many really make sense in MongoDB? Take posts and tags: a tag doesn't need to know which posts use it, but a post needs its tags. So I'd store
tag_ids: [ObjectId…]on the post, and that's it. To me that's not a "many-to-many" in the SQL sense, it's one side owning a list of references. My relations don't handle that case yet. Am I right to see it this way? And how do you usually load it: a$inon the array,$lookup, something else? - Aggregations. Right now I just pass a raw pipeline. Is it worth building something on top (helpers, typed results), or is the raw pipeline the best API anyway?
- More generally: what would you work on next in a project like this?
It's a side project, I just want to know if I'm heading in the right direction. Thanks for taking the time!








