ywh/doctrine-encryption-extension
ywh/doctrine-encryption-extension adds transparent field-level encryption to Doctrine entities, with configurable DBAL types and event subscribers for securely storing sensitive data in PHP applications.
Architecture fit. This is a Doctrine ORM extension, not a Laravel/Eloquent package. It hooks Doctrine's event system (metadata driver + lifecycle events) to transparently encrypt annotated entity properties on flush and decrypt them on hydration. That means it fits only if the target application already runs Doctrine inside Laravel (via laravel-doctrine/orm) or is a Symfony/standalone Doctrine codebase. For a conventional Eloquent-based Laravel app, the architectural fit is poor: adopting this package implies adopting Doctrine as a second ORM alongside Eloquent, which is a much larger decision than "add field-level encryption."
Integration feasibility. Mechanically straightforward in a Doctrine context: register an event subscriber, mark sensitive properties with the package's annotation/attribute, supply a key and cipher configuration, and register the metadata driver. In Laravel this requires custom service-provider wiring and configuration plumbing that the package does not ship. There is no Laravel service provider, no config file, no facade, no published migrations — all glue code is the adopter's responsibility.
Technical risk.
.env is the likely default, and that is a materially weaker posture than the encryption suggests.LIKE-searched, range-filtered, sorted, or joined on. Without a blind-index/searchable-encryption feature, any existing query touching the column breaks or must move to the application layer.VARCHAR(255) columns silently truncate or error depending on strict mode.Key questions.
WHERE, ORDER BY, JOIN, or unique constraints today?Stack fit. Assess against the actual runtime:
| Dimension | Fit | Note |
|---|---|---|
| Eloquent-only Laravel app | Poor | Requires introducing Doctrine; disproportionate |
Laravel + laravel-doctrine/orm |
Moderate | Native use case, but still custom provider wiring |
| Symfony / standalone Doctrine | Good | Intended environment |
| Mixed Eloquent + Doctrine | Risky | Two persistence paths over the same tables; encryption only applies to one |
Migration path.
TEXT/LONGTEXT (or BLOB) companion columns rather than widening existing ones under load. On MySQL, TEXT avoids index-length and row-size cliffs.ALTER + rewrite on large tables.Compatibility. Pin explicitly and verify against the Laravel/Doctrine version matrix: PHP minor (attributes require 8.0+), Doctrine ORM major (event system changed across 2.x/3.x), DBAL type mapping, and whether the metadata driver still uses doctrine/annotations (deprecated in favor of attributes). Test against the exact DB engine and strict-mode settings — truncation behavior differs between MySQL and PostgreSQL.
Sequencing. Ship in this order: (1) Doctrine integration and subscriber wiring with a no-op cipher to prove lifecycle hooks fire correctly on insert/update/hydrate; (2) key management and rotation design; (3) encryption on one low-risk column end-to-end in staging; (4) query-surface remediation; (5) production backfill. Treat step 1 as a spike whose exit criterion is "we understand exactly which events fire on our entities" — that knowledge is what makes the vendor risk tolerable.
Recommendation on sourcing. Given zero adoption and the security-critical surface, benchmark against paragonie/ciphersweet (blind indexing, mature audit trail, framework-agnostic) and a hand-rolled Eloquent custom cast wrapping sodium_crypto_secretbox for Eloquent apps. If this package is chosen, vendor it (copy into the repo) rather than depend on it, so upstream abandonment cannot block a security patch.
Maintenance. Effectively unmaintained by any reasonable definition: no dependents means no one is filing issues, no release cadence is visible, and the maintainer's incentive (a bug-bounty platform publishing an internal utility) does not extend to supporting external consumers. Plan for the fork to be yours. Budget ongoing ownership: PHP/Doctrine major upgrades, cipher deprecations in OpenSSL/sodium, and dependency CVEs in a package that touches cryptography.
Support. No SLA, no security contact documented, no CVE history to assess responsiveness. For a component in the confidentiality path, absence of a disclosure process is itself a finding. Escalation path is "read the source."
Scaling. Encryption cost is per-value per-row on write and per-row on read; for typical payloads this is noise against network I/O, but it becomes visible in bulk export, report generation, and queue workers hydrating large result sets. The bigger scaling issue is architectural: losing server-side filtering on encrypted columns pushes predicates into PHP, which turns indexed queries into full scans plus memory pressure. Quantify this before committing — a 10M-row table filtered in application code will not scale, and no amount of tuning fixes it.
Failure modes.
Ramp-up. Low code-learning curve (annotation + subscriber), high organizational learning curve (key custody, rotation drills, incident response for crypto failure, query-surface constraints communicated to every engineer who writes a repository method). Estimate the real cost as key-management engineering plus a query audit, not package integration — and staff accordingly. The most likely correct outcome of this evaluation is "adopt the pattern, not the package."
How can I help you explore Laravel packages today?