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.
DateTime) via Symfony Serializer. That's the single biggest decision this de-risks: one database instead of two.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."jsonb_document type. If your infra roadmap involves SQLite, MariaDB oddities, or serverless MySQL, this constrains it.#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.Adopt when:
$casts = ['misc' => 'array'] or Laravel's json cast is sufficient, this package adds nothing.Look elsewhere / push back when:
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.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.
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.
How can I help you explore Laravel packages today?