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 Slug Bundle Laravel Package

chamber-orchestra/doctrine-slug-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Bundle Add to your composer.json:

    composer require chamber-orchestra/doctrine-slug-bundle
    

    Enable in config/bundles.php:

    return [
        // ...
        ChamberOrchestra\DoctrineSlugBundle\ChamberOrchestraDoctrineSlugBundle::class => ['all' => true],
    ];
    
  2. Annotate an Entity Use the #[Slug] attribute on a property (e.g., title):

    use ChamberOrchestra\DoctrineSlugBundle\Attribute\Slug;
    
    #[ORM\Entity]
    class Article
    {
        #[Slug]
        #[ORM\Column(length: 255)]
        private string $title;
    
        #[ORM\Column(length: 255, unique: true)]
        private string $slug;
    }
    
  3. First Use Case Save an Article instance—slugs auto-generate on persist()/flush():

    $article = new Article();
    $article->setTitle("Laravel 10 Features");
    $entityManager->persist($article);
    $entityManager->flush(); // Slug auto-populates (e.g., "laravel-10-features")
    

Implementation Patterns

Workflow: Slug Generation

  1. Attribute-Based Configuration Customize slug behavior via attributes:

    #[Slug(
        generator: 'custom', // Use a custom generator service
        separator: '-',
        unique: true,       // Auto-increment on collision (e.g., "-1")
        fields: ['title', 'category'] // Multi-field slugs
    )]
    
  2. Event-Driven Hooks Subscribe to SlugGenerateEvent for pre/post-processing:

    use ChamberOrchestra\DoctrineSlugBundle\Event\SlugGenerateEvent;
    
    $dispatcher->addListener(SlugGenerateEvent::class, function (SlugGenerateEvent $event) {
        $event->setSlug(strtolower($event->getSlug()));
    });
    
  3. Multi-Entity Integration Reuse generators across entities by tagging services:

    # config/services.yaml
    services:
        App\Slug\CustomGenerator:
            tags: [chamber_orchestra.doctrine_slug.generator]
    

Laravel-Specific Tips

  • Doctrine ORM Bridge: Use doctrine/orm (v2.11+) via spatie/laravel-doctrine-orm for Laravel integration.
  • Form Requests: Auto-generate slugs in handle():
    public function handle(): void
    {
        $this->validate();
        $model = new Article($this->validated());
        $entityManager->persist($model);
        $entityManager->flush(); // Slug auto-populates
    }
    

Gotchas and Tips

Pitfalls

  1. Collision Handling

    • Default behavior appends -1, -2 on duplicates. Override via unique: false or a custom generator.
    • Debug Tip: Check SlugGenerateEvent payload for collision details.
  2. Circular Dependencies

    • Avoid bidirectional relationships where slug fields reference each other (e.g., Article slug → Category slug).
    • Fix: Use #[Slug(unique: false)] or lazy-load slugs.
  3. Case Sensitivity

    • Slugs default to lowercase. Normalize early:
    #[Slug(separator: '_', unique: true)]
    private string $name; // "Hello World" → "hello_world"
    

Debugging

  • Event Dumping: Log SlugGenerateEvent:
    $dispatcher->addListener(SlugGenerateEvent::class, function ($event) {
        \Log::debug('Slug generation:', [
            'entity' => $event->getEntity(),
            'input' => $event->getInput(),
            'slug' => $event->getSlug(),
        ]);
    });
    
  • Generator Overrides: Clear cached generators after changes:
    php bin/console cache:clear
    

Extension Points

  1. Custom Generators Implement SlugGeneratorInterface:

    use ChamberOrchestra\DoctrineSlugBundle\SlugGenerator\SlugGeneratorInterface;
    
    class CustomSlugGenerator implements SlugGeneratorInterface
    {
        public function generate(array $input): string
        {
            return str_replace(' ', '-', $input['title']);
        }
    }
    

    Register in services.yaml:

    services:
        App\Slug\CustomSlugGenerator:
            tags: [chamber_orchestra.doctrine_slug.generator]
    
  2. Doctrine Lifecycle Events Hook into prePersist/preUpdate for manual control:

    use Doctrine\ORM\Event\LifecycleEventArgs;
    
    $entity->addLifecycleCallback(function ($entity, LifecycleEventArgs $args) {
        if ($args->getEventName() === 'prePersist') {
            $entity->setSlug('custom-slug');
        }
    });
    
  3. Testing Mock slug generation in PHPUnit:

    $this->getContainer()->get('chamber_orchestra.doctrine_slug.generator.custom')
        ->expects($this->once())
        ->method('generate')
        ->willReturn('test-slug');
    
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.
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
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