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

Entity Traits Bundle Laravel Package

danilovl/entity-traits-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation

    composer require danilovl/entity-traits-bundle
    

    Register the bundle in config/bundles.php (if not using Symfony Flex):

    Danilovl\EntityTraitsBundle\EntityTraitsBundle::class => ['all' => true],
    
  2. Configure Create config/packages/danilovl_entity_traits.yaml with basic settings:

    danilovl_entity_traits:
        identity:
            default_strategy: uuid
        timestampable:
            enabled: true
            timezone: 'UTC'
        soft_delete:
            enabled: true
    
  3. First Use Case Add traits to an entity (e.g., Article):

    use Danilovl\EntityTraitsBundle\Trait\Required\Identity\UuidTrait;
    use Danilovl\EntityTraitsBundle\Trait\Optional\Timestampable\TimestampableTrait;
    
    #[ORM\Entity]
    class Article
    {
        use UuidTrait;
        use TimestampableTrait;
    }
    

    Run php bin/console doctrine:schema:update --force to generate the database schema.


Implementation Patterns

Common Workflows

  1. Entity Boilerplate Reduction Replace repetitive fields (e.g., createdAt, updatedAt, slug) with traits:

    use Danilovl\EntityTraitsBundle\Trait\Optional\Timestampable\TimestampableTrait;
    use Danilovl\EntityTraitsBundle\Trait\Optional\Seo\SlugTrait;
    
    class BlogPost
    {
        use TimestampableTrait;
        use SlugTrait;
    }
    
  2. Audit Trails Track creation/modification by users:

    use Danilovl\EntityTraitsBundle\Trait\Optional\Audit\BlameableTrait;
    
    class Product
    {
        use BlameableTrait;
    }
    

    Configure blameable.user_class to point to your User entity.

  3. Soft Deletes Enable soft deletes globally or per-entity:

    danilovl_entity_traits:
        soft_delete:
            enabled: true
    

    Use SoftDeletableTrait in entities:

    use Danilovl\EntityTraitsBundle\Trait\Optional\Timestampable\SoftDeletableTrait;
    
    class Comment
    {
        use SoftDeletableTrait;
    }
    
  4. Validation Add validators directly to properties:

    use Danilovl\EntityTraitsBundle\Validator\Email;
    
    class User
    {
        #[Email]
        protected ?string $email = null;
    }
    
  5. Hierarchical Data Use TreePathTrait + #[Tree] attribute for nested structures:

    use Danilovl\EntityTraitsBundle\Trait\Optional\Sorting\TreePathTrait;
    use Danilovl\EntityTraitsBundle\Attribute\Tree;
    
    #[Tree]
    class Category
    {
        use TreePathTrait;
    }
    
  6. Presets Leverage pre-built trait combinations (e.g., BlogPostTrait):

    use Danilovl\EntityTraitsBundle\Trait\Preset\BlogPostTrait;
    
    class Article
    {
        use BlogPostTrait;
    }
    

Integration Tips

  1. Doctrine Filters Enable global filters (e.g., SoftDeleteFilter) via config or manually:

    doctrine:
        orm:
            filters:
                soft_delete:
                    class: Danilovl\EntityTraitsBundle\Doctrine\Filter\SoftDeleteFilter
                    enabled: true
    
  2. Event Listeners Extend default listeners (e.g., SluggableListener) by overriding methods in a custom listener:

    class CustomSluggableListener extends SluggableListener
    {
        protected function generateSlug(string $value): string
        {
            return strtolower(parent::generateSlug($value));
        }
    }
    

    Register it as a service with danilovl_entity_traits.sluggable_listener tag.

  3. Custom Traits Extend existing traits for domain-specific logic:

    trait CustomTimestampableTrait extends TimestampableTrait
    {
        public function isRecent(int $hours = 24): bool
        {
            return $this->getCreatedAt()->getTimestamp() > strtotime("-{$hours} hours");
        }
    }
    
  4. Configuration Overrides Override bundle config per-environment (e.g., config/packages/dev/danilovl_entity_traits.yaml):

    danilovl_entity_traits:
        timestampable:
            timezone: 'Europe/Paris'
    
  5. Testing Mock listeners in tests:

    $container->get('danilovl_entity_traits.timestampable_listener')->setTimezone('UTC');
    

Gotchas and Tips

Pitfalls

  1. Identity Strategy Conflicts

    • Issue: Using IdTrait, UuidTrait, and UlidTrait in the same entity causes conflicts.
    • Fix: Choose one identity strategy per entity (e.g., UuidTrait for all UUID-based entities).
  2. Required vs. Optional Traits

    • Issue: Mixing Required and Optional traits for the same field type (e.g., NameTrait vs. Optional\Content\NameTrait) can lead to type mismatches.
    • Fix: Stick to one variant per field (e.g., always Optional for nullable fields).
  3. Soft Delete Filter Auto-Registration

    • Issue: Forgetting to enable soft_delete.filter_auto_enable means the filter won’t apply globally.
    • Fix: Set filter_auto_enable: true in config or register manually.
  4. Blameable Without User Class

    • Issue: Enabling blameable.enabled: true without setting blameable.user_class throws exceptions.
    • Fix: Always define user_class when blameable.enabled is true.
  5. Timestampable Timezone Mismatches

    • Issue: Using UTC in config but expecting local time in queries.
    • Fix: Be explicit about timezone handling (e.g., ->setTimezone(new \DateTimeZone('UTC'))).
  6. TreePathListener Performance

    • Issue: Rebuilding path/depth on every flush for large hierarchies.
    • Fix: Disable auto-rebuild with #[Tree(autoRebuild: false)] and manually trigger updates.
  7. Validator Overrides

    • Issue: Custom validators not being picked up.
    • Fix: Ensure they’re tagged with validator.constraint_validator:
      services:
          App\Validator\CustomEmailValidator:
              tags: ['validator.constraint_validator']
      
  8. Attribute Conflicts

    • Issue: Multiple #[AutoSlug] attributes on one entity.
    • Fix: Use class-level attributes (not property-level) for global slug sources.

Debugging Tips

  1. Listener Debugging

    • Enable debug mode to see listener execution:
      $this->get('danilovl_entity_traits.timestampable_listener')->setDebug(true);
      
  2. Schema Validation

    • Use doctrine:schema:validate to catch mapping issues:
      php bin/console doctrine:schema:validate
      
  3. Event Dispatching

    • Check if listeners are triggered by enabling Symfony’s event dispatcher debug:
      $dispatcher->addListener(Events::PRE_PERSIST, function ($event) {
          error_log('Event triggered for: ' . get_class($event->getObject()));
      });
      
  4. Trait Overrides

    • Verify trait methods are not overridden by parent classes:
      if (method_exists($this, 'getSlug')) {
          // Method exists (either from trait or parent)
      }
      

Extension Points

  1. Custom Listeners Extend base listeners (e.g., TimestampableListener) to add logic:

    class CustomTimestampableListener extends TimestampableListener
    {
        public function prePersist(LifecycleEventArgs $args): void
        {
            parent::prePersist($args);
            // Add custom logic
        }
    }
    

    Register it as a service with the same tag as the original listener.

  2. Dynamic Trait Loading Use PHP’s class_uses() to inspect traits at runtime:

    if (in_array(\Danilovl\EntityTraitsBundle\Trait\Optional\Audit\BlameableTrait::class, class_uses($entity))) {
        // Entity has BlameableTrait
    }
    
  3. Attribute Interceptors Create custom attributes to extend functionality:

    #[Attribute]
    class AutoHash
    {
        public function __construct(public string $property, public string $algorithm = 'sha256') {}
    }
    

    Register a listener to handle the attribute.

  4. Doctrine Events Hook into Doctrine events for custom logic:

    $
    
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