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 Key Value Storage Bundle Laravel Package

dontdrinkandroot/doctrine-key-value-storage-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require dontdrinkandroot/doctrine-key-value-storage-bundle
    

    Add to config/bundles.php (Symfony):

    return [
        // ...
        DontDrinkAndRoot\DoctrineKeyValueStorageBundle\DontDrinkAndRootDoctrineKeyValueStorageBundle::class => ['all' => true],
    ];
    
  2. Entity Configuration Define a Doctrine entity with the KeyValueStorage trait:

    use DontDrinkAndRoot\DoctrineKeyValueStorageBundle\Entity\KeyValueStorage;
    
    /**
     * @ORM\Entity
     */
    class UserSettings
    {
        use KeyValueStorage;
    
        // Your entity fields...
    }
    
  3. First Use Case Store/retrieve a typed value in a Laravel-like context:

    $settings = new UserSettings();
    $settings->setString('theme', 'dark'); // Store as string
    $settings->setInt('notifications', 5); // Store as integer
    $settings->setBoolean('is_active', true);
    
    // Later...
    $theme = $settings->getString('theme'); // Returns 'dark'
    $notifications = $settings->getInt('notifications'); // Returns 5
    

Implementation Patterns

Common Workflows

  1. Dynamic Configuration Storage Use for user-specific or app-wide settings:

    // In a service
    public function updateUserPreferences(User $user, array $prefs) {
        $settings = $user->getSettings(); // Assume relation to UserSettings
        foreach ($prefs as $key => $value) {
            $settings->setString($key, $value);
        }
        $entityManager->persist($settings);
    }
    
  2. Caching Layer Combine with Symfony Cache for performance:

    $cache = $this->container->get('cache.app');
    $key = 'user_prefs_' . $user->getId();
    if (!$cache->has($key)) {
        $settings = $entityManager->getRepository(UserSettings::class)->findOneBy(['user' => $user]);
        $cache->set($key, $settings->getAll(), 3600);
    }
    
  3. Validation Hooks Override set* methods to enforce business rules:

    public function setInt($key, $value) {
        if ($key === 'max_retries' && $value > 10) {
            throw new \InvalidArgumentException('Max retries cannot exceed 10');
        }
        parent::setInt($key, $value);
    }
    

Integration Tips

  • Doctrine Events: Listen to prePersist/preUpdate to auto-generate keys or validate:
    $eventManager->addEventListener(
        KernelEvents::CONTROLLER,
        [$this, 'onKernelController']
    );
    
  • QueryBuilder: Filter entities by key-value pairs:
    $qb = $entityManager->createQueryBuilder()
        ->select('u')
        ->from(UserSettings::class, 'u')
        ->where('u.getString("theme") = :theme')
        ->setParameter('theme', 'dark');
    
  • Migrations: Use DoctrineMigrationsBundle to handle schema changes safely.

Gotchas and Tips

Pitfalls

  1. Type Safety

    • Issue: getString() on a non-string key returns null, not a casted value. Fix: Use getValue() + manual casting or add a getCastedValue($key, $type) helper.
    • Workaround: Validate types before storage:
      if (!is_int($value)) throw new \InvalidArgumentException('Must be integer');
      
  2. Performance

    • Issue: getAll() loads all key-value pairs into memory. Fix: Use findByKey() or limit keys in queries:
      $qb->andWhere('u.key IN (:keys)')
        ->setParameter('keys', ['theme', 'notifications']);
      
  3. Serialization

    • Issue: Complex objects (e.g., DateTime) may not serialize/deserialize correctly. Fix: Implement __toString() or use setJson() for complex data:
      $settings->setJson('preferences', ['last_login' => $user->getLastLogin()]);
      
  4. Doctrine Lifecycle

    • Issue: Detached entities lose key-value data. Fix: Reattach or refresh:
      $entityManager->refresh($settings);
      

Debugging Tips

  • Enable SQL Logging:
    $entityManager->getConnection()->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger());
    
  • Check for Stale Data: Use getMetadata() to inspect entity state:
    var_dump($settings->getMetadata()->getFieldValue('key_value_data'));
    
  • Event Listeners: Log prePersist/preUpdate to debug key-value changes:
    $event->getObject()->getKeyValueData(); // Inspect raw data
    

Extension Points

  1. Custom Types Extend the trait to add setFloat(), setArray(), etc.:

    public function setFloat($key, $value) {
        $this->keyValueData[$key] = ['type' => 'float', 'value' => $value];
    }
    
  2. Encryption Override set* methods to encrypt sensitive data:

    use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
    
    public function setString($key, $value) {
        $this->keyValueData[$key] = [
            'type' => 'string',
            'value' => $this->encoder->encode($value)
        ];
    }
    
  3. TTL (Time-to-Live) Add expiration logic via Doctrine lifecycle callbacks:

    use Doctrine\ORM\Mapping as ORM;
    
    /**
     * @ORM\PreUpdate
     */
    public function checkExpiration() {
        if ($this->expiry && $this->expiry < new \DateTime()) {
            $this->keyValueData = [];
        }
    }
    
  4. Bulk Operations Create a repository method for batch updates:

    public function bulkUpdate(array $updates, User $user) {
        $settings = $this->findOneBy(['user' => $user]);
        foreach ($updates as $key => $value) {
            $settings->setString($key, $value);
        }
        $this->getEntityManager()->flush();
    }
    
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.
directorytree/privacy-filter-classifier
directorytree/privacy-filter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony
spatie/flare-daemon-runtime