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 Encrypt Bundle Laravel Package

coka/doctrine-encrypt-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require coka/doctrine-encrypt-bundle
    

    Add to config/bundles.php (Symfony) or config/packages/doctrine.yaml (Laravel via Symfony components):

    CedrickOka\DoctrineEncryptBundle\CedrickOkaDoctrineEncryptBundle::class => ['all' => true],
    
  2. Configuration Define encryption keys in .env:

    DOCTRINE_ENCRYPT_KEY=your_secure_256bit_key_here
    DOCTRINE_ENCRYPT_IV=your_16byte_iv_here
    

    (Or configure via config/packages/doctrine_encrypt.yaml if using Symfony.)

  3. First Use Case Encrypt a field in an entity:

    use Doctrine\ORM\Mapping as ORM;
    use CedrickOka\DoctrineEncryptBundle\Type\EncryptedType;
    
    #[ORM\Entity]
    class User {
        #[ORM\Column(type: EncryptedType::NAME)]
        private $creditCardNumber;
    }
    

    The bundle automatically handles encryption/decryption on read/write.


Implementation Patterns

Common Workflows

  1. Field-Level Encryption Use EncryptedType for sensitive fields (e.g., password, ssn, api_keys):

    #[ORM\Column(type: EncryptedType::NAME, options: ["encrypted" => true])]
    private $apiKey;
    
  2. Custom Encryption Logic Extend the base type for custom algorithms:

    use CedrickOka\DoctrineEncryptBundle\Type\AbstractEncryptedType;
    
    class CustomEncryptedType extends AbstractEncryptedType {
        protected function encrypt($value): string {
            return openssl_encrypt($value, 'aes-256-cbc', $this->key, 0, $this->iv);
        }
    }
    

    Register in services.yaml:

    services:
        App\Type\CustomEncryptedType:
            tags: [doctrine.type]
    
  3. Querying Encrypted Fields Avoid direct queries on encrypted fields. Use application logic or store hashed values separately:

    // Bad: Querying encrypted field directly
    $user = $entityManager->createQueryBuilder()
        ->where('u.creditCardNumber = :cc')
        ->getQuery()
        ->getOneOrNullResult();
    
    // Good: Use a hashed column for comparisons
    #[ORM\Column(type: 'string', length: 64)]
    private $creditCardHash;
    
  4. Bulk Operations For mass updates, disable encryption temporarily (use with caution):

    $entityManager->getConnection()->getConfiguration()->setSQLLogger(null);
    // Perform bulk operations
    $entityManager->flush();
    

Integration Tips

  • Laravel Eloquent: Use Doctrine via doctrine/orm or laravel-doctrine/orm for hybrid projects.
  • Migrations: Encrypted fields appear as TEXT in migrations. Document this in schema updates.
  • Testing: Mock the encryption service in unit tests:
    $this->mock(EncryptionService::class)
         ->shouldReceive('encrypt')
         ->andReturn('encrypted_value');
    

Gotchas and Tips

Pitfalls

  1. Key Management

    • Hardcoding keys in .env is insecure for production. Use a secrets manager (e.g., AWS KMS, HashiCorp Vault).
    • Rotate keys periodically and handle legacy data decryption.
  2. Performance Overhead

    • Encryption adds ~10-50ms per field. Benchmark for high-write workloads.
    • Avoid encrypting frequently queried fields (e.g., email for login).
  3. Doctrine Events

    • Encryption triggers prePersist, preUpdate, and preFlush events. Override these carefully:
      #[ORM\PrePersist]
      public function prePersist() {
          // Avoid double-encryption if using lifecycle callbacks
      }
      
  4. Database Compatibility

    • Some databases (e.g., SQLite) may fail on large encrypted blobs. Test with your target DB.
  5. Serialization Issues

    • Encrypted fields break JSON serialization in APIs. Use @Groups (API Platform) or manual serialization:
      #[Groups(['api'])]
      public function getMaskedCard(): string {
          return '****-' . substr($this->creditCardNumber, -4);
      }
      

Debugging

  • Corrupted Data: If decryption fails, check:

    • Key/IV mismatch in .env.
    • Database corruption (backup/restore may help).
    • Use dd($entityManager->getConnection()->getDatabasePlatform()) to verify platform support.
  • Logs: Enable Doctrine logging to trace encryption:

    doctrine:
        dbal:
            logging: true
            profiling: true
    

Extension Points

  1. Custom Types Extend AbstractEncryptedType for non-OpenSSL encryption (e.g., sodium_crypto_secretbox):

    class SodiumEncryptedType extends AbstractEncryptedType {
        protected function encrypt($value): string {
            return sodium_crypto_secretbox($value, random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES), $this->key);
        }
    }
    
  2. Field-Level Configuration Override encryption per field via YAML:

    App\Entity\User:
        properties:
            creditCardNumber:
                type: encrypted
                options:
                    algorithm: aes-128-cbc
                    key: custom_key_here
    
  3. Event Subscribers Listen to preEncrypt/postDecrypt events for auditing:

    #[AsEventListener(event: 'preEncrypt', method: 'onPreEncrypt')]
    public function onPreEncrypt(PreEncryptEventArgs $args) {
        // Log sensitive data access
    }
    

Pro Tips

  • Partial Encryption: Use EncryptedType with nullable: true for optional fields.
  • Backup Strategy: Encrypted data requires keys to restore. Document key backup procedures.
  • Compliance: Pair with doctrine/extensions for GDPR right-to-erasure support:
    $entityManager->createQueryBuilder()
        ->update(User::class, 'u')
        ->set('u.creditCardNumber', ':empty')
        ->where('u.id = :id')
        ->getQuery()
        ->execute();
    
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.
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
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