ywh/doctrine-encryption-bundle
A Symfony bundle that adds transparent field-level encryption to Doctrine entities, encrypting sensitive columns at rest via Doctrine DBAL types and event listeners. Configure keys and ciphers to protect data with minimal changes to existing mappings.
Architecture fit — this is not a Laravel package. ywh/doctrine-encryption-bundle is a Symfony bundle: a DI extension plus compiler passes that register Doctrine ORM types and event subscribers around ywh/doctrine-encryption-extension. Laravel has no bundle/service-container-shape equivalent, and Laravel's default ORM is Eloquent, not Doctrine. If the target application is Laravel (as framed), the bundle contributes zero reusable code — its only conceivable value is the underlying extension, which itself assumes a Doctrine ORM entity/persistence layer most Laravel apps do not run. The realistic value is as a reference design, not a dependency.
Integration feasibility — low. The package is scoped to the Symfony 2 generation, which reached end of life in November 2018. Expect composer constraints in the PHP 5.6–7.x and Doctrine ORM 2.4–2.5 range; modern stacks (PHP 8.2+, Symfony 6/7, DBAL 3/4, ORM 2.15+/3.x) have removed or relocated the type-registration and lifecycle-event APIs this bundle hooks into. Verify composer.json before treating this as definitive, but plan on the assumption that installation fails or forces a dependency downgrade of the application framework.
Technical risk — high, and concentrated in the most sensitive layer. Field-level encryption is a security-critical code path. The hard problems are not the cipher call; they are ciphertext format versioning, key rotation, randomized-vs-deterministic encryption (deterministic is required for equality search, which is exactly what the ORM type abstraction tends to hide), null/empty semantics, and safe behavior on re-save (double encryption). An unmaintained crypto wrapper with a 2-star, zero-dependent footprint has no external security review surface, no CVE triage, and no published test coverage claims. A defect here is silent, irreversible, and discovered at audit or breach time.
Key questions to resolve before any decision:
defuse/php-encryption, paragonie/halite)?Stack fit. Treat this as out-of-fit for a Laravel codebase and low fit for a modern Symfony one. The idiomatic Laravel substitute is Eloquent casts — the built-in encrypted cast for opaque fields, Casts\Attribute for custom envelopes — and paragonie/ciphersweet (via a thin service-provider wrapper) if blind-indexed, searchable encryption is the actual requirement. For "encrypt at rest, no search needed," database-native TDE or the framework cast is cheaper and better supported. Only pursue Doctrine-in-Laravel if the org already runs it; note that the Doctrine integration packages for Laravel are themselves thinly maintained, which compounds, not reduces, the risk.
Migration path. Do not introduce this greenfield. If it already exists in an inherited Symfony2/Doctrine service, the correct move is an exit plan, not an expansion: (1) inventory every encrypted column and its consuming queries; (2) build a dual-read path that decrypts via the vendor and re-encrypts under a maintained library with a versioned envelope; (3) backfill in batches; (4) remove the dependency. Because this is crypto, the transition must be reversible at the data layer — never mutate ciphertext in place without a verified decrypt path and a full backup.
Compatibility. Confirm three things concretely: PHP constraint, Doctrine DBAL/ORM constraint, and whether the encryption type is registered through an API that still exists. Any one failing converts "integrate" into "fork and own," which changes the economics entirely.
Sequencing. Requirements clarification (do we need searchability, or just at-rest opacity?) → threat model and compliance driver → build-vs-buy decision → PoC against a maintained alternative → only then consider a fork of this codebase. The framework-layer decision (bundle vs. service provider vs. cast) should follow, not lead, the crypto decision.
Maintenance. Upstream activity is effectively nil. Adopting this transfers permanent ownership: PHP version bumps, dependency security patches, DBAL API migrations, and crypto review all become internal work. The carrying cost of a maintained third-party library is almost always lower than the carrying cost of a hand-held fork of an abandoned one — and for crypto the asymmetry is severe.
Support. No vendor, no SLA, no triage. MIT gives you the code and no warranty. The escalation path for a production incident is the on-call engineer reading unfamiliar Symfony2 internals under pressure.
Scaling. Per-row CPU cost is real but modest; the structural cost is indexing. Randomized encryption removes the ability to filter or sort in SQL, forcing application-side filtering or full table scans on any encrypted column. Key material sits in the application process; there is no KMS/HSM integration, so envelope-encryption patterns must be built around it.
Failure modes worth naming explicitly: lost or rotated keys producing unrecoverable rows; mixed plaintext/ciphertext during partial rollout; silent double encryption on entity re-save; encrypted values leaking into logs, queue payloads, or API serialization; broken joins and unique constraints on encrypted columns; and — the worst case — a crypto weakness that is undetectable until it matters. Each needs a detection or rollback story before go-live.
Ramp-up. Documentation is minimal and written for a Symfony2 audience. A Laravel team would absorb the Doctrine event/type lifecycle largely from source. Budget days for comprehension and, if forking, weeks before the first safe production write.
How can I help you explore Laravel packages today?