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 Behaviors Laravel Package

knplabs/doctrine-behaviors

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require knplabs/doctrine-behaviors
    

    Add the bundle to config/bundles.php (Symfony) or register the extension in config/services.php (Laravel via DoctrineBundle).

  2. First Use Case: Add a behavior trait to an entity. For example, to enable Blameable (track creator/updater):

    // src/Entity/Post.php
    namespace App\Entity;
    
    use Doctrine\ORM\Mapping as ORM;
    use Knp\DoctrineBehaviors\Model\Blameable\BlameableTrait;
    
    #[ORM\Entity]
    class Post
    {
        use BlameableTrait;
    
        #[ORM\Column(type: 'string', length: 255)]
        private $title;
    
        // ... other fields
    }
    

    Configure the blameable behavior in config/packages/doctrine_behaviors.yaml (Symfony) or config/doctrine_behaviors.php (Laravel):

    knp_doctrine_behaviors:
        orm:
            blameable:
                creator_field: createdBy
                updater_field: updatedBy
    
  3. Verify: Run migrations (php bin/console doctrine:migrations:diffphp bin/console doctrine:migrations:migrate) and test CRUD operations. Check if createdBy/updatedBy fields auto-populate.


Implementation Patterns

Common Workflows

  1. Entity-Level Behaviors:

    • Timestampable: Auto-manage createdAt/updatedAt:

      use Knp\DoctrineBehaviors\Model\Timestampable\TimestampableTrait;
      class Post { use TimestampableTrait; }
      

      Configure in doctrine_behaviors.yaml:

      knp_doctrine_behaviors:
          orm:
              timestampable: true
      
    • SoftDeletable: Add isDeleted flag and delete() method:

      use Knp\DoctrineBehaviors\Model\SoftDeletable\SoftDeletableTrait;
      class Post { use SoftDeletableTrait; }
      

      Query soft-deleted records:

      $repository->createQueryBuilder('p')
          ->where('p.isDeleted = :val')
          ->setParameter('val', false);
      
  2. Repository-Level Behaviors:

    • Tree: Enable nested set or materialized path for hierarchical data:
      // src/Repository/CategoryRepository.php
      use Knp\DoctrineBehaviors\ORM\Tree\TreeTrait;
      class CategoryRepository extends EntityRepository { use TreeTrait; }
      
      Configure in doctrine_behaviors.yaml:
      knp_doctrine_behaviors:
          orm:
              tree:
                  repository_class: App\Repository\CategoryRepository
      
      Use methods like getChildren(), getParent(), or move().
  3. Translatable Entities:

    • Define a Translation entity and link it to the main entity:
      // src/Entity/PostTranslation.php
      use Knp\DoctrineBehaviors\Model\Translatable\TranslationInterface;
      class PostTranslation implements TranslationInterface { ... }
      
      // src/Entity/Post.php
      use Knp\DoctrineBehaviors\Model\Translatable\TranslatableTrait;
      class Post { use TranslatableTrait; }
      
      Configure locales and fields:
      knp_doctrine_behaviors:
          orm:
              translatable:
                  locale_field: locale
                  translation_class: App\Entity\PostTranslation
                  translations: { title: Title, content: Content }
      
      Access translations:
      $post->translate()->setTitle('Français', 'Nouveau titre');
      
  4. Sluggable:

    • Auto-generate SEO-friendly slugs:
      use Knp\DoctrineBehaviors\Model\Slugable\SlugableTrait;
      class Post { use SlugableTrait; }
      
      Configure in doctrine_behaviors.yaml:
      knp_doctrine_behaviors:
          orm:
              sluggable:
                  fields: ['title']
      

Integration Tips

  • Custom Fields: Override behavior fields in the entity:
    class Post {
        use BlameableTrait;
        public function setCreatedBy(?User $user): self { /* custom logic */ }
    }
    
  • Event Listeners: Extend behavior logic via Doctrine events:
    // src/EventListener/PostListener.php
    use Doctrine\ORM\Event\PreUpdateEventArgs;
    class PostListener {
        public function preUpdate(Post $post, PreUpdateEventArgs $args) {
            if ($post->isDirty('title')) {
                $post->setSlug($post->getTitle());
            }
        }
    }
    
  • APIs: Use behaviors to enforce business rules (e.g., SoftDeletable for RESTful soft deletes).

Gotchas and Tips

Pitfalls

  1. Migration Order:

    • Always run migrations after adding behavior traits to entities. Fields like createdAt or isDeleted must exist before the trait is used.
  2. Circular References:

    • Translatable: Ensure the Translation entity is properly mapped with a OneToMany/ManyToOne relationship to avoid infinite loops in serialization (e.g., JSON API).
  3. Repository Conflicts:

    • Tree: If extending a custom repository, ensure the TreeTrait is loaded after parent traits to avoid method conflicts. Use parent::method() explicitly if needed.
  4. Locale Handling:

    • Translatable: Default locale must be set in the translatable config or via setTranslatableLocale(). Missing locales cause NULL translations.
  5. Slug Collisions:

    • Sluggable: Default behavior appends a number to duplicate slugs (e.g., post-2). Customize via sluggable config:
      knp_doctrine_behaviors:
          orm:
              sluggable:
                  unique_suffix_max_length: 4
      
  6. UUID Generation:

    • Uuidable: Ensure the uuid field is defined as string(36) or binary(16) in the entity mapping. Auto-generation requires ramsey/uuid:
      composer require ramsey/uuid
      

Debugging

  • Missing Fields: Verify doctrine_behaviors.yaml config matches entity field names (e.g., createdBy vs created_by).
  • Tree Errors: Check for TreeException if nodes are orphaned or paths are invalid. Use getPath() to debug:
    $category->getPath(); // Should return "/1/4/7/" for materialized path
    
  • Translatable Issues: Enable SQL logging to confirm translations are saved:
    # config/packages/dev/doctrine.yaml
    doctrine:
        dbal:
            logging: true
            logging_format: '%%SQL%%'
    

Extension Points

  1. Custom Behaviors:

    • Extend existing traits or create new ones by implementing DoctrineBehaviors\ORM\BehaviorInterface.
  2. Event Subscribers:

    • Hook into behavior lifecycle events (e.g., onFlush for Timestampable):
      use Knp\DoctrineBehaviors\ORM\Event\LifecycleEventArgs;
      class CustomSubscriber implements EventSubscriber {
          public function prePersist(LifecycleEventArgs $args) {
              $entity = $args->getEntity();
              if ($entity instanceof TimestampableInterface) {
                  $entity->setCreatedAt(new \DateTime());
              }
          }
      }
      
  3. QueryBuilder Extensions:

    • Add custom methods to repository traits:
      // src/Repository/TreeRepository.php
      trait TreeRepository {
          public function getSiblings(EntityInterface $entity) {
              return $this->createQueryBuilder('e')
                  ->where('e.parent = :parent')
                  ->andWhere('e.id != :id')
                  ->setParameter('parent', $entity->getParent())
                  ->setParameter('id', $entity->getId())
                  ->getQuery()
                  ->getResult();
          }
      }
      
  4. PHPStan:

    • Leverage the extension for IDE autocompletion:
      composer require --dev knplabs/doctrine-behaviors-phpstan
      
    • Example: TranslatableInterface::getTranslations() now returns TranslatableTranslationCollection instead of array.

Configuration Quirks

  • Symfony vs. Laravel:
    • Laravel users must manually register the extension in config/services.php:
      $container->loadFromExtension('doctrine_behaviors', [
          'orm' => [
              'timestampable' => true,
              'bl
      
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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui