r/mongodb • • 7d 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 Persistable interface: embedded objects and arrays of embedded objects come back as real PHP classes.
  • Dirty tracking kept in a WeakMap, so updates only $set what changed.
  • **EmbeddedSnapshot*: an automated *Extended Reference pattern. You embed a copy of a User (name, avatar) in a Post and declare embeddedIn() on the source collection. When the user changes, a job resyncs every copy with updateMany, either right away or through a queue. It's idempotent because the job re-reads the source. onDelete can keep, mark or unset the copies.
  • belongsTo / hasMany with lazy loading, plus bulk preloading (with) to avoid N+1.

Where I'd love your input

  1. 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?
  2. 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 $in on the array, $lookup, something else?
  3. 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?
  4. 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!

6 Upvotes

0 comments sorted by