coka/doctrine-secret-type-bundle
Installation:
composer require coka/doctrine-secret-type-bundle
Add the bundle to config/bundles.php (Symfony) or register it in AppKernel.php (legacy):
CedrickOka\DoctrineSecretTypeBundle\DoctrineSecretTypeBundle::class => ['all' => true],
Configuration:
Add encryption settings to config/packages/doctrine_secret_type.yaml:
doctrine_secret_type:
encryption_key: '%env(ENCRYPTION_KEY)%' # Must be 32 chars for AES-256
algorithm: 'AES-256-CBC' # Default; adjust if needed
First Use Case: Define a Doctrine entity field to encrypt:
use Doctrine\DBAL\Types\Types;
use CedrickOka\DoctrineSecretTypeBundle\DBAL\Types\SecretType;
/**
* @ORM\Entity
*/
class User {
/**
* @ORM\Column(type=SecretType::NAME)
*/
private $apiToken;
}
Entity Mapping:
Use SecretType for sensitive fields (passwords, tokens, API keys):
/**
* @ORM\Column(type=SecretType::NAME, options={"encrypted"=true})
*/
private $creditCardNumber;
Repository Integration: The type handles encryption/decryption transparently. Querying works as usual:
$user = $repo->findOneBy(['apiToken' => $encryptedToken]); // Decrypted internally
Custom Type Extension:
Override default behavior by extending SecretType:
use CedrickOka\DoctrineSecretTypeBundle\DBAL\Types\SecretType as BaseSecretType;
class CustomSecretType extends BaseSecretType {
public function convertToDatabaseValue($value, AbstractPlatform $platform) {
// Custom logic (e.g., pre-processing)
return parent::convertToDatabaseValue($value, $platform);
}
}
Register in doctrine.yaml:
dbal:
types:
custom_secret: CedrickOka\CustomSecretTypeBundle\DBAL\Types\CustomSecretType
Migration Strategy: For existing databases, use a migration to encrypt data:
$entityManager->getConnection()->executeStatement(
'UPDATE users SET api_token = ? WHERE id = ?',
[$encryptedValue, $userId]
);
security.yaml for password hashing:
security:
encoders:
App\Entity\User:
algorithm: auto
options:
secret_type: true # Use SecretType for storage
#[Groups(['api:user:read'])]
#[ORM\Column(type=SecretType::NAME)]
private $apiToken;
$this->mockEncryptionService->shouldReceive('encrypt')->andReturn('mocked');
Key Management:
%env(ENCRYPTION_KEY)%).Database Compatibility:
BLOB/TEXT for encrypted values (default storage type).VARCHAR limits if encrypting large strings.Query Limitations:
WHERE clauses for direct comparisons (e.g., WHERE api_token = ?). Use application logic instead:
if ($user->getApiToken()->equals($providedToken)) { ... }
Performance:
private $decryptedApiToken;
public function getApiToken() {
return $this->decryptedApiToken ?? $this->decryptedApiToken = $this->apiToken->decrypt();
}
Encryption Failures:
ENCRYPTION_KEY length (must be 32 chars for AES-256).Doctrine Errors:
SecretType isn’t recognized, clear the cache:
php bin/console cache:clear
bundles.php.Data Corruption:
$encrypted = $secretType->convertToDatabaseValue('test123', $platform);
$decrypted = $secretType->convertToPHPValue($encrypted, $platform);
assert($decrypted === 'test123');
Custom Algorithms:
Extend CedrickOka\DoctrineSecretTypeBundle\Encryption\EncrypterInterface:
class CustomEncrypter implements EncrypterInterface {
public function encrypt($value) { ... }
public function decrypt($value) { ... }
}
Register in services.yaml:
services:
CedrickOka\DoctrineSecretTypeBundle\Encryption\EncrypterInterface: '@App\Encryption\CustomEncrypter'
Field-Level Configuration: Use metadata to customize per-field:
/**
* @ORM\Column(type=SecretType::NAME, options={
* "encrypted"=true,
* "algorithm"="AES-128-CBC",
* "key"="%env(FIELD_SPECIFIC_KEY)%"
* })
*/
private $fieldSpecificSecret;
Event Listeners: Hook into lifecycle events for pre/post encryption logic:
$entityManager->getEventManager()->addEventListener(
\Doctrine\ORM\Events::prePersist,
function ($event) {
$entity = $event->getObject();
if ($entity instanceof User) {
$entity->setApiToken($entity->getApiToken()->encrypt());
}
}
);
$logger->info('Decrypted API token for user', ['user_id' => $user->getId()]);
doctrine_secret_type:
encryption_key: '%env(ENCRYPTION_KEY_%kernel.environment%)%'
How can I help you explore Laravel packages today?