kyzegs/doctrine-encryption-bundle
A Symfony bundle for Doctrine ORM that adds transparent field-level encryption for sensitive entity data, with configurable encryptors to help protect information at rest while keeping mappings and application code simple.
This is a Doctrine bundle, so in Laravel you need Doctrine present (laravel-doctrine/orm or a manual DBAL/ORM wiring) before anything here applies. Steps:
composer require kyzegs/doctrine-encryption-bundle:^2.0 (note the major bump — see Gotchas before upgrading an existing install).config/bundles.php in Symfony; in Laravel, add the DBAL types and the subscriber/event hooks in config/doctrine.php).Encrypted attribute, or declare a column as the new encrypted_text DBAL type.First realistic use case: encrypting PII (email, phone, national ID) on a Doctrine-mapped model while still being able to query it by exact match via the blind index.
Read the upgrade doc shipped with v2.0.0 first if you have any v1.x data — it is the authoritative source on what changed in the ciphertext format.
Attribute-driven encryption. Keep the mapping declarative: #[Encrypted] on the property, blind index declared as a sibling attribute/column. Business logic never touches encrypt/decrypt — it writes plaintext, Doctrine handles the rest on flush/hydrate.
Blind index for lookups. The new query helper (PR #3) is the headline feature. Pattern: store the HMAC-based blind index in a separate indexed column and query it through the helper rather than hand-rolling hash_hmac. Exact-match only — no LIKE, no range queries, no ordering on the encrypted value.
encrypted_text DBAL type. Use it when you want the column type itself to carry the encryption contract (useful for schema diffing and for models where attributes are awkward). Register the type in your DBAL type map before running migrations, or schema tooling will emit a plain TEXT column.
Repository/service boundaries. Wrap blind-index lookups in repository methods (findByEmail(string $email)) so callers never see the hash. This keeps key/pepper changes contained to one layer.
Migration and re-encryption workflow. v2 makes dry runs read every value. Use that as a pre-flight validation pass in staging: dry run first, inspect the report for undecryptable or malformed rows, then run for real. Wire it into a queued job for large tables rather than a request.
Integration tip. In Laravel, register the DBAL type and any event subscribers in a service provider's boot() and gate it behind config('encryption.enabled') so tests and local seeds can run unencrypted if needed.
TEXT) and remember index columns need their own length budget.phpunit.xml and reset DB state between tests; encrypted attributes make raw dump/diff assertions noisy and unreadable.How can I help you explore Laravel packages today?