brandoriented/doctrine-encryption-bundle
Installation:
composer require brandoriented/doctrine-encryption-bundle dev-master
Add the bundle to AppKernel.php:
new BrandOriented\Encryption\DoctrineEncryptionBundle(),
Configure:
Add basic encryption settings to config/packages/doctrine_encryption.yaml:
doctrine_encryption:
key: '%env(ENCRYPTION_KEY)%'
iv: '%env(ENCRYPTION_IV)%'
suffix: '_encrypted'
First Use Case: Encrypt a field in an entity:
use BrandOriented\Encryption\Annotation\Encrypted;
class User {
/**
* @Encrypted()
*/
private $sensitiveData;
}
The field will auto-encrypt on prePersist/preUpdate.
Entity Encryption:
@Encrypted() annotation on Doctrine entity properties.prePersist, preUpdate).class Patient {
/**
* @Encrypted()
*/
private $ssn;
}
Manual Encryption/Decryption:
Bridge service in controllers/services:
use BrandOriented\Encryption\Bridge\Bridge;
public function __construct(private Bridge $bridge) {}
public function handleSensitiveData() {
$encrypted = $this->bridge->encrypt('secret');
$decrypted = $this->bridge->decrypt($encrypted);
}
Twig Integration:
{{ user.ssn | decrypt }} {# Outputs decrypted SSN #}
Custom Encryptor:
doctrine_encryption:
class: 'App\Service\CustomEncryptor'
BrandOriented\Encryption\EncryptorInterface.Environment Variables:
Store key and iv in .env (e.g., ENCRYPTION_KEY=your_32_byte_key).
Use Symfony’s %env() in config for security.
Doctrine Events:
Extend existing events (e.g., preFlush) for bulk operations:
$em->getEventManager()->addEventListener(
Doctrine\ORM\Events::preFlush,
[$this, 'encryptAllSensitiveData']
);
Migrations: Avoid encrypting existing data in migrations. Use raw SQL or manual decryption first.
No postLoad Handling:
postLoad. Fields remain encrypted in memory unless manually decrypted.postLoad:
$em->getEventManager()->addEventListener(
Doctrine\ORM\Events::postLoad,
[$this, 'decryptEntityFields']
);
Suffix Collisions:
suffix config (e.g., _encrypted) is appended to encrypted values.user_email_encrypted vs. user_email_encrypted), decryption fails._enc_${random_string}).Key Rotation:
key/iv in config and re-encrypt data:
php bin/console doctrine:query-sql "UPDATE users SET ssn = :encrypted WHERE 1"
--param=encrypted: '...' {# Newly encrypted value #}
Performance:
Verify Encryption: Compare plaintext vs. encrypted values:
$encrypted = $this->bridge->encrypt('test');
$decrypted = $this->bridge->decrypt($encrypted);
assert($decrypted === 'test');
Check Annotations:
Ensure @Encrypted() is correctly placed (no typos, valid Doctrine property).
Logs: Enable Doctrine logging to debug lifecycle events:
doctrine:
orm:
logging: true
Custom Encryptor:
Implement EncryptorInterface for non-AES methods (e.g., RSA):
class RSAEncryptor implements EncryptorInterface {
public function encrypt($data) { /* ... */ }
public function decrypt($data) { /* ... */ }
}
Dynamic Suffixes: Override the suffix per entity/field:
/**
* @Encrypted(suffix="custom_suffix")
*/
private $field;
Exclude Fields: Use a custom listener to skip encryption for specific fields:
$em->getEventManager()->addEventListener(
Doctrine\ORM\Events::prePersist,
function ($event) {
$entity = $event->getObject();
if (isset($entity->skipEncryption)) {
$event->setNewObject($entity); // Bypass encryption
}
}
);
Query Filtering: Use DQL functions to query encrypted fields (requires custom DQL functions):
$qb->andWhere('FUNCTION("decrypt", u.ssn) = :ssn')
->setParameter('ssn', '123-45-6789');
How can I help you explore Laravel packages today?