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

Doctrine Json Odm Laravel Package

dunglas/doctrine-json-odm

Store PHP objects as JSON documents in PostgreSQL JSONB or MySQL JSON columns alongside traditional Doctrine ORM mappings, enabling schema-less, NoSQL-like hybrid data models with fast querying and indexing.

View on GitHub
Deep Wiki
Context7

Product Decisions This Supports

  • Build vs. buy for "custom fields" / variable-schema features. Instead of standing up MongoDB, DynamoDB, or an EAV table, you get a JSON/JSONB column on an existing relational entity that round-trips real PHP object graphs (POPOs, nested objects, enums, UUIDs, DateTime) via Symfony Serializer. That's the single biggest decision this de-risks: one database instead of two.
  • Hybrid data model roadmap. Core commerce/CMS/CRM data stays relationally modeled and indexed; the long tail (product attributes per category, tenant-specific settings, CMS block trees, form-submission payloads, third-party webhook bodies, feature flags, audit/event snapshots) lives in a document column. This unblocks "arbitrary attributes" epics without a schema migration per customer.
  • Scope negotiation on schema changes. A PM can trade "another 6 migrations and a release train" against "add one document column and ship." That directly shortens time-to-market for per-customer customization requests.
  • Query capability is the guardrail on scope. Postgres JSONB supports indexed path queries and is roughly MongoDB-class for read performance; DQL support requires adding scienta/doctrine-json-functions or dropping to native SQL. So this supports "store flexibly, filter on a few known keys" — not "build a document database."
  • Deployment/platform decision. Commits you to PostgreSQL ≥ 9.4 or MySQL ≥ 5.7.8, and to Doctrine DBAL 4.3+ if you want the native jsonb_document type. If your infra roadmap involves SQLite, MariaDB oddities, or serverless MySQL, this constrains it.
  • Migration/refactor planning. Without type aliases, the persisted #type key is the PHP FQCN — a namespace rename becomes a data-migration task (the README even ships the JSON_REPLACE query). Adopting type aliases from day one is a cheap decision now that buys refactor freedom later.

When to Consider This Package

Adopt when:

  • You're on Doctrine ORM in a PHP app (Symfony or API Platform are first-class; Laravel is not — see caveat below) and already run Postgres or MySQL.
  • You need genuine object-graph fidelity on the way back out, not just a decoded assoc array. If $casts = ['misc' => 'array'] or Laravel's json cast is sufficient, this package adds nothing.
  • The document is read and written as a whole aggregate (a settings blob, a content block tree), with only a handful of queried keys that you can index.
  • You want the escape hatch of a second datastore without the operational cost of one.

Look elsewhere / push back when:

  • You're a Laravel/Eloquent shop. This is not a Laravel package: no service provider, no config publish, no facade. You'd add doctrine/orm + symfony/serializer, register the DBAL type in a provider's boot(), and hand-build the serializer stack. That's a real integration cost and a second ORM in the codebase — usually a "no" unless Doctrine is already present.
  • You need relational integrity, foreign keys, or cross-document joins into the nested data. Don't; it's schema-less by design.
  • Heavy write contention on one row, or large documents. Every save rewrites the whole column; partial updates aren't a thing. High-frequency mutable state belongs in proper columns or a real document DB.
  • You need rich server-side querying inside documents as a product feature. Native SQL only, plus an optional third-party DQL extension; that's a dependency you don't control.
  • Nested-mutation correctness matters and your team won't internalize the caveat. Doctrine's reference-based dirty checking means in-place nested edits can silently not persist; the documented workaround is cloning. This is a repeat-bug class, not a one-time gotcha — budget for a convention or a wrapper.

Dependency-risk read: 630 stars, listed as 0 dependents (weak ecosystem signal), a single dominant maintainer, and a very thin surface — a DBAL custom type plus a serializer wrapper. The thinness is the mitigation: MIT license, a few hundred lines, forkable in an afternoon. Low lock-in; the lock-in that does exist is the data shape in your JSON column and the #type keys already written to production.

How to Pitch It (Stakeholders)

To executives (one paragraph): We can ship per-customer custom fields and flexible content models without adding a second database or a second on-call surface. This open-source MIT library (used in the Symfony/API Platform ecosystem, maintained by Kévin Dunglas) lets us store arbitrary PHP data structures in a JSON column alongside our normal relational tables, queryable with native database indexes. Net effect: faster delivery on customization requests, one datastore to operate, and no vendor lock-in — the library is small and we could maintain a fork if needed.

To engineering (the honest version): It's a DBAL column type that serializes objects through Symfony Serializer and denormalizes them back. Integration is a Composers install plus type registration and a serializer stack — trivial in Symfony, a deliberate decision in Laravel where it means pulling Doctrine in. Requirements: Postgres 9.4+/MySQL 5.7.8+, DBAL 4.3+ for the native jsonb_document type. Two mandatory conventions before we write a line of product code: (1) define type aliases in the type map so production documents don't encode PHP FQCNs, and (2) establish a rule that nested documents are cloned (or reassigned wholesale) before mutation, or we will ship silent no-op UPDATEs. Add scienta/doctrine-json-functions only if we need DQL access to JSON paths.

Recommended next step: a 2–3 day spike on one real feature — one document column, type aliases configured, one indexed JSONB path query against a realistic row count, and an explicit test that a nested mutation persists. That spike resolves the two open questions (integration cost in our stack; query performance at our data volume) that determine whether this is a build-vs-buy win or just a clever escape hatch.

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.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route