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 Encrypted Field Laravel Package

aeliot/doctrine-encrypted-field

Laravel/Doctrine extension that transparently encrypts and decrypts entity fields. Adds an encrypted field type you can map in your entities so sensitive values are stored encrypted in the database and handled normally in your code.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require aeliot/doctrine-encrypted-field
    

    Add to your composer.json under extra:

    "doctrine": {
        "orm": {
            "mappings": {
                "App": {
                    "is_bundle": false,
                    "type": "xml",
                    "dir": "config/doctrine",
                    "prefix": "App\\Models",
                    "alias": "App"
                }
            }
        }
    }
    
  2. Configure Encryption In config/doctrine.php, add:

    'encryption' => [
        'enabled' => true,
        'key' => env('ENCRYPTION_KEY', 'your-32-byte-key-here'),
        'algorithm' => 'AES-256-CBC',
        'options' => 0,
    ],
    
  3. First Use Case: Encrypting a Field Annotate a field in your entity:

    use Aeliot\DoctrineEncryptedField\Annotation\Encrypted;
    
    /**
     * @ORM\Entity
     */
    class User {
        /**
         * @ORM\Column(type="string", length=255)
         * @Encrypted
         */
        private $ssn;
    }
    
  4. Run Migrations

    php artisan doctrine:migrations:diff
    php artisan doctrine:migrations:migrate
    

Implementation Patterns

Workflow: Secure Data Handling

  1. Entity Definition Use @Encrypted on sensitive fields (e.g., password, credit_card, ssn).

    /**
     * @Encrypted
     * @ORM\Column(type="string", length=255)
     */
    private $apiKey;
    
  2. Repository Layer Fetch encrypted data seamlessly:

    $user = $userRepository->find($id);
    // $user->ssn is automatically decrypted when accessed.
    
  3. Form Handling (Symfony) Bind encrypted fields in forms:

    $form = $this->createFormBuilder($user)
        ->add('ssn', TextType::class, [
            'mapped' => true, // Automatically encrypts on submit
        ])
        ->getForm();
    
  4. API Responses (Laravel) Use toArray() or jsonSerialize()—encrypted fields are decrypted automatically:

    return response()->json($user->toArray());
    

Integration Tips

  • Caching: Decrypted data is cached per request. Clear cache if encryption keys rotate:
    \Aeliot\DoctrineEncryptedField\EncryptionManager::clearCache();
    
  • Querying Encrypted Fields Avoid direct queries on encrypted fields. Use application logic or add computed columns:
    /**
     * @ORM\Column(type="string", length=255)
     */
     private $encryptedEmailHash;
    
     /**
      * @ORM\Column(type="string", length=255)
      * @Encrypted
      */
     private $email;
    
     public function getEmailHash(): string {
         return hash('sha256', $this->email);
     }
    
  • Bulk Operations Use EntityManager batch processing for efficiency:
    $em->flush(); // Triggers decryption/encryption in bulk.
    

Gotchas and Tips

Pitfalls

  1. Key Management

    • Never hardcode keys in production. Use environment variables or a secrets manager.
    • Key rotation: If the key changes, all encrypted data becomes unreadable. Plan for migration:
      php artisan doctrine:encrypted-fields:migrate-keys --old-key=old_key --new-key=new_key
      
    • Backup encrypted data before rotating keys.
  2. Performance Overhead

    • Encryption/decryption adds ~10-20ms per field. Benchmark for high-traffic fields.
    • Mitigation: Cache decrypted values in the entity or use a read replica for analytics.
  3. Database Indexes

    • Encrypted fields cannot be indexed directly. Use computed columns or application-level indexes:
      /**
       * @ORM\Column(type="string", length=64)
       */
       private $emailSha256;
      
  4. Doctrine Events

    • Avoid manually setting encrypted fields in prePersist/preUpdate—let the library handle it:
      // ❌ Anti-pattern
      $user->setSsn(encrypt($ssn));
      
      // ✅ Correct
      $user->setSsn($ssn); // Library encrypts automatically.
      
  5. Serialization

    • Encrypted fields are not serialized in serialize()/unserialize(). Use jsonSerialize() for APIs.

Debugging

  1. Enable Logging Add to config/doctrine.php:

    'encryption' => [
        'debug' => env('APP_DEBUG', false),
    ],
    

    Logs appear in storage/logs/laravel.log.

  2. Verify Encryption Check raw database values:

    $em->getConnection()->fetchAll('SELECT ssn FROM user WHERE id = ?', [$id]);
    

    Compare with decrypted values in PHP.

  3. Common Errors

    • "Invalid key length": Ensure the key is 32 bytes for AES-256.
    • "Field not encrypted": Verify @Encrypted annotation and enabled: true in config.
    • Slow queries: Use EXPLAIN to check for full-table scans on encrypted fields.

Extension Points

  1. Custom Algorithms Extend the encryption manager:

    use Aeliot\DoctrineEncryptedField\EncryptionManager;
    
    class CustomEncryptionManager extends EncryptionManager {
        protected function getAlgorithm(): string {
            return 'AES-128-GCM';
        }
    }
    

    Register in config/doctrine.php:

    'encryption' => [
        'manager' => \App\Services\CustomEncryptionManager::class,
    ],
    
  2. Field-Level Configuration Override defaults per field:

    /**
     * @Encrypted(algorithm="AES-128-CBC", options=OpenSSL::PKCS7_PADDING)
     */
    private $legacyField;
    
  3. Non-Doctrine ORM Use the core encryption service standalone:

    use Aeliot\DoctrineEncryptedField\EncryptionService;
    
    $service = new EncryptionService();
    $encrypted = $service->encrypt('sensitive_data');
    $decrypted = $service->decrypt($encrypted);
    
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