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

Eav Model Bundle Laravel Package

sidus/eav-model-bundle

Symfony/Doctrine bundle to build dynamic EAV models from versioned YAML config. Generate forms automatically, validate/translate/serialize easily, and contextualize attribute data across unlimited axes (language, region, channel, version, etc.). Extensible and customizable.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require sidus/eav-model-bundle
    

    Enable the bundle in config/bundles.php:

    return [
        // ...
        Sidus\EAVModelBundle\SidusEAVModelBundle::class => ['all' => true],
    ];
    
  2. Define a Model: Create a YAML config file (e.g., config/eav_models/my_model.yml):

    my_model:
        class: App\Entity\MyModel
        attributes:
            - name: title
              type: string
              required: true
            - name: description
              type: text
              required: false
    
  3. Generate Entities: Run the bundle’s command to scaffold entities:

    php bin/console sidus:eav:generate
    
  4. First Use Case: Fetch and manipulate data via the repository:

    $repository = $this->getDoctrine()->getRepository(MyModel::class);
    $model = $repository->findOneBy(['id' => 1]);
    $model->setAttribute('title', 'New Title');
    $repository->save($model);
    

Key First Steps

  • Configuration: Start with config/eav_models/ for YAML definitions.
  • Doctrine Integration: Ensure App\Entity\* paths are correct in YAML.
  • Contexts: Explore Documentation/09-context.md for multi-axis contextualization (e.g., language, user role).
  • Forms: Use Sidus\EAVModelBundle\Form\Type\EAVModelType for dynamic forms (see Documentation/05.1-form.md).

Implementation Patterns

Core Workflows

  1. Dynamic Attribute Management:

    • Add/remove attributes via YAML without migrations:
      # config/eav_models/my_model.yml
      attributes:
          - name: new_field
            type: boolean
            default: false
      
    • Regenerate entities:
      php bin/console sidus:eav:generate
      
  2. Contextual Data Handling:

    • Define contexts in YAML (e.g., language, user_group):
      contexts:
          - name: language
            type: string
            default: en
      
    • Access contextualized data:
      $model->setContext('language', 'fr');
      $value = $model->getAttribute('title', [], ['language' => 'fr']);
      
  3. Form Integration:

    • Use the bundle’s form type for dynamic rendering:
      $form = $this->createForm(EAVModelType::class, $model, [
          'model_config' => 'my_model',
          'contexts' => ['language' => 'en'],
      ]);
      
  4. Querying:

    • Filter by attributes or contexts:
      $models = $repository->findBy([
          'attributes.title' => 'Search Term',
          'contexts.language' => 'es',
      ]);
      

Integration Tips

  • Symfony Events: Listen to sidus_eav_model.pre_save or sidus_eav_model.post_load for custom logic:

    $eventDispatcher->addListener(SidusEAVModelEvents::PRE_SAVE, function (PreSaveEvent $event) {
        $model = $event->getModel();
        // Custom validation or transformation
    });
    
  • Validation: Leverage Symfony’s validators via YAML:

    attributes:
        - name: email
          type: string
          validation: { constraints: { Email: ~ } }
    
  • APIs: Use serializers with @Groups for API responses:

    #[Groups(['api'])]
    public function getAttribute(string $name, array $context = [], array $contexts = []): ?string
    
  • Testing: Mock contexts in tests:

    $model = $repository->find(1);
    $model->setContext('test_context', 'value');
    $this->assertEquals('value', $model->getContext('test_context'));
    

Gotchas and Tips

Pitfalls

  1. YAML Parsing Errors:

    • Issue: Typos in YAML (e.g., type: str instead of type: string) cause silent failures.
    • Fix: Validate YAML with a linter (e.g., yamllint) before generating entities.
  2. Context Overrides:

    • Issue: Contexts are merged hierarchically. Overriding a parent context may not behave as expected.
    • Fix: Explicitly set all required contexts when querying:
      $model->getAttribute('title', [], ['language' => 'fr', 'user_group' => 'admin']);
      
  3. Attribute Type Mismatches:

    • Issue: Storing a string in a boolean field (or vice versa) corrupts data.
    • Fix: Use strict type casting in YAML:
      attributes:
          - name: is_active
            type: boolean
            default: false
            validation: { constraints: { Type: { type: "bool" } } }
      
  4. Regeneration Pitfalls:

    • Issue: Running sidus:eav:generate after adding a required attribute to an existing model may break data.
    • Fix: Add attributes as required: false first, migrate data, then set required: true and regenerate.

Debugging

  1. Doctrine Events: Enable SQL logging to debug queries:

    # config/packages/dev/doctrine.yaml
    doctrine:
        dbal:
            logging: true
            profiling: true
    
  2. Context Dumping: Log contexts for debugging:

    \Symfony\Component\Debug\Debug::dump($model->getContexts());
    
  3. Form Errors:

    • Clear cache after YAML changes:
      php bin/console cache:clear
      
    • Check form errors with:
      $form->getErrors(true); // Deep errors
      

Extension Points

  1. Custom Attribute Types: Extend Sidus\EAVModelBundle\Model\Attribute\AttributeInterface for custom types (e.g., Json, DateRange):

    class JsonAttribute implements AttributeInterface
    {
        public function getValue($model, $context = []): ?string
        {
            return json_encode($model->getRawAttribute($this->getName()));
        }
    }
    

    Register in YAML:

    attributes:
        - name: metadata
          type: json
    
  2. Custom Context Providers: Implement Sidus\EAVModelBundle\Context\ContextProviderInterface to inject dynamic contexts (e.g., from a session):

    class UserContextProvider implements ContextProviderInterface
    {
        public function getContexts(): array
        {
            return ['user_id' => $this->getUserId()];
        }
    }
    

    Register as a service:

    services:
        Sidus\EAVModelBundle\Context\ContextProviderInterface:
            tags: ['sidus_eav.context_provider']
    
  3. Event Subscribers: Extend model behavior via events (e.g., audit logs):

    $eventDispatcher->addListener(SidusEAVModelEvents::POST_SAVE, function (PostSaveEvent $event) {
        $logger->info('Model saved', ['model_id' => $event->getModel()->getId()]);
    });
    

Configuration Quirks

  1. Default Contexts:

    • Behavior: If no default context is set in YAML, the model falls back to an empty array.
    • Fix: Always define defaults:
      contexts:
          - name: language
            default: en
      
  2. Attribute Inheritance:

    • Behavior: Attributes are not inherited between models. Each YAML file is isolated.
    • Workaround: Use shared YAML snippets or a base model with a extends field (not natively supported; requires custom logic).
  3. Case Sensitivity:

    • Issue: Attribute names in YAML are case-sensitive but Doctrine may normalize them.
    • Fix: Use consistent casing (e.g., snake_case) and avoid mixed case.

Performance Tips

  1. Context Indexing:

    • For large datasets, index contextualized attributes:
      // In a custom repository method
      $qb->andWhere('m.contexts LIKE :context')
        ->setParameter('context', '%"language":"fr"%');
      
  2. Batch Updates:

    • Use Doctrine’s BATCH_SIZE for bulk operations:
      # config/packages/doctrine.yaml
      doctrine:
          orm:
              dql:
                  string_trim: true
                  batch_size: 50
      
  3. Caching:

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.
croct/coding-standard
croct/plug-php
nqxcode/phpmorphy
boundwize/pyrameter
testo/facade
headercat/phpstan-extension-ide-helper
yosymfony/parser-utils
innmind/black-box
babenkoivan/elastic-migrations
babenkoivan/elastic-adapter
develia/commons
dmstr/symfony-system-resources-bundle
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
renatomarinho/laravel-page-speed
develia/geo-bundle
austinheap/laravel-database-encryption
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle