Installation
composer require drjele/doctrine-encrypt
Add to config/app.php under providers:
Drjele\DoctrineEncrypt\DoctrineEncryptServiceProvider::class,
Publish Config
php artisan vendor:publish --provider="Drjele\DoctrineEncrypt\DoctrineEncryptServiceProvider"
Configure encryption keys in .env:
DOCTRINE_ENCRYPT_KEY=your-32-byte-key-here
DOCTRINE_ENCRYPT_CIPHER=AES-256-CBC
First Use Case Encrypt a field in an Eloquent model:
use Drjele\DoctrineEncrypt\Type\EncryptedType;
class User extends Model {
protected $casts = [
'credit_card' => EncryptedType::class,
];
}
Now User::create(['credit_card' => '4111111111111111']) will store an encrypted value.
Field-Level Encryption
Use EncryptedType in $casts for automatic encryption/decryption:
protected $casts = [
'ssn' => EncryptedType::class,
'medical_history' => EncryptedType::class,
];
Query Filtering
Encrypted fields can be queried with raw SQL (avoid where clauses on encrypted fields):
// ❌ Avoid
User::where('credit_card', 'like', '4111%')->get();
// ✅ Use raw SQL for exact matches
User::whereRaw("credit_card = ENCRYPT('4111111111111111', ?)", [config('doctrine-encrypt.key')])->get();
Bulk Operations
Use update/create with encrypted arrays:
User::create([
'name' => 'John Doe',
'encrypted_data' => ['key1' => 'value1', 'key2' => 'value2'], // Auto-encrypted if casted
]);
Custom Encryption Logic
Extend EncryptedType for per-field rules:
class CustomEncryptedType extends EncryptedType {
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) {
$fieldDeclaration['comment'] = 'Custom encrypted field';
return parent::getSQLDeclaration($fieldDeclaration, $platform);
}
}
API Responses
Use toArray() or toJson()—decryption happens automatically:
return User::find(1)->toArray(); // 'credit_card' is decrypted
Key Management
.env keys to version control.config('doctrine-encrypt.key') for dynamic keys (e.g., from AWS KMS).Performance Overhead
email for login).Database Compatibility
AES_ENCRYPT/AES_DECRYPT (requires AES plugin).pgp_sym_encrypt/pgp_sym_decrypt (install pgcrypto extension).Serialization Issues
remember_token).unique constraints or whereRaw with dynamic values.Migration Pitfalls
User::all()->each(fn ($user) => $user->forceFill(['ssn' => $user->ssn])->save());
Verify Encryption Check raw DB values with:
\DB::select("SELECT credit_card FROM users WHERE id = ?", [1]);
Should return gibberish (e.g., ��⸮�⸮�⸮�⸮).
Key Validation If decryption fails, test the key:
$encrypted = \Drjele\DoctrineEncrypt\Encryptor::encrypt('test', config('doctrine-encrypt.key'));
\Drjele\DoctrineEncrypt\Encryptor::decrypt($encrypted, config('doctrine-encrypt.key')); // Should return 'test'
Logging
Enable debug mode in config/doctrine-encrypt.php:
'debug' => env('DOCTRINE_ENCRYPT_DEBUG', false),
Logs encryption/decryption events to storage/logs/laravel.log.
Custom Ciphers
Implement Drjele\DoctrineEncrypt\EncryptorInterface:
class ChaCha20Encryptor implements EncryptorInterface {
public function encrypt($data, $key) { /* ... */ }
public function decrypt($data, $key) { /* ... */ }
}
Bind it in AppServiceProvider:
$this->app->bind(EncryptorInterface::class, ChaCha20Encryptor::class);
Field-Specific Config Override defaults per field:
protected $casts = [
'ssn' => [
'type' => EncryptedType::class,
'cipher' => 'AES-128-CBC',
'key' => 'custom-key-for-ssn',
],
];
Event Listeners Hook into encryption events (e.g., log sensitive data access):
\Drjele\DoctrineEncrypt\Events\Encrypting::class => [YourListener::class, 'handle'],
How can I help you explore Laravel packages today?