Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Doctrine Secret Type Bundle Laravel Package

coka/doctrine-secret-type-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. 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],
    
  2. 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
    
  3. 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;
    }
    

Implementation Patterns

Common Workflows

  1. Entity Mapping: Use SecretType for sensitive fields (passwords, tokens, API keys):

    /**
     * @ORM\Column(type=SecretType::NAME, options={"encrypted"=true})
     */
    private $creditCardNumber;
    
  2. Repository Integration: The type handles encryption/decryption transparently. Querying works as usual:

    $user = $repo->findOneBy(['apiToken' => $encryptedToken]); // Decrypted internally
    
  3. 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
    
  4. Migration Strategy: For existing databases, use a migration to encrypt data:

    $entityManager->getConnection()->executeStatement(
        'UPDATE users SET api_token = ? WHERE id = ?',
        [$encryptedValue, $userId]
    );
    

Integration Tips

  • Symfony Security: Combine with security.yaml for password hashing:
    security:
        encoders:
            App\Entity\User:
                algorithm: auto
                options:
                    secret_type: true  # Use SecretType for storage
    
  • API Responses: Exclude encrypted fields from serialization:
    #[Groups(['api:user:read'])]
    #[ORM\Column(type=SecretType::NAME)]
    private $apiToken;
    
  • Testing: Mock the encryption service:
    $this->mockEncryptionService->shouldReceive('encrypt')->andReturn('mocked');
    

Gotchas and Tips

Pitfalls

  1. Key Management:

    • Never hardcode keys in source. Use environment variables (%env(ENCRYPTION_KEY)%).
    • Rotate keys periodically and re-encrypt data (use a migration).
  2. Database Compatibility:

    • Ensure your DB supports BLOB/TEXT for encrypted values (default storage type).
    • Avoid VARCHAR limits if encrypting large strings.
  3. Query Limitations:

    • Encrypted fields cannot be used in WHERE clauses for direct comparisons (e.g., WHERE api_token = ?). Use application logic instead:
      if ($user->getApiToken()->equals($providedToken)) { ... }
      
  4. Performance:

    • Encryption adds overhead. Avoid encrypting frequently queried fields or large blobs.
    • Cache decrypted values in memory if accessed often:
      private $decryptedApiToken;
      
      public function getApiToken() {
          return $this->decryptedApiToken ?? $this->decryptedApiToken = $this->apiToken->decrypt();
      }
      

Debugging

  1. Encryption Failures:

    • Check ENCRYPTION_KEY length (must be 32 chars for AES-256).
    • Verify the algorithm is supported by your PHP OpenSSL extension.
  2. Doctrine Errors:

    • If SecretType isn’t recognized, clear the cache:
      php bin/console cache:clear
      
    • Ensure the bundle is loaded after Doctrine in bundles.php.
  3. Data Corruption:

    • Test decryption with a known value:
      $encrypted = $secretType->convertToDatabaseValue('test123', $platform);
      $decrypted = $secretType->convertToPHPValue($encrypted, $platform);
      assert($decrypted === 'test123');
      

Extension Points

  1. 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'
    
  2. 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;
    
  3. 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());
            }
        }
    );
    

Pro Tips

  • Audit Logs: Log encryption/decryption events for compliance:
    $logger->info('Decrypted API token for user', ['user_id' => $user->getId()]);
    
  • Backup Strategy: Include encrypted data in backups (decrypt during restore).
  • Multi-Environment: Use environment-specific keys:
    doctrine_secret_type:
        encryption_key: '%env(ENCRYPTION_KEY_%kernel.environment%)%'
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle