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

Tag Bundle Laravel Package

edumedia/tag-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation

    composer require edumedia/tag-bundle
    

    Add the bundle to config/bundles.php:

    return [
        // ...
        eduMedia\TagBundle\TagBundle::class => ['all' => true],
    ];
    
  2. Define Core Entities Create Tag and Tagging entities as shown in the README. These are the foundational models for the bundle.

  3. Tag an Entity Use the TagService to attach tags to any entity:

    use eduMedia\TagBundle\Service\TagService;
    
    // In a controller or service
    $tagService = $this->container->get(TagService::class);
    $user = $this->entityManager->getRepository(User::class)->find(1);
    $tagService->tag($user, ['laravel', 'php']);
    
  4. Fetch Tags Retrieve tags for an entity:

    $tags = $tagService->getTags($user);
    

First Use Case

Categorize Blog Posts

  • Create a Post entity implementing TaggableInterface.
  • Use TagService to assign tags like ['laravel', 'tutorial'] to posts.
  • Display tags in a template:
    {% for tag in post.tags %}
        <span class="tag">{{ tag.name }}</span>
    {% endfor %}
    

Implementation Patterns

Workflows

  1. Tagging Entities

    • Dynamic Tagging: Use TagService::tag() to attach tags to any entity (e.g., User, Post).
      $tagService->tag($entity, ['tag1', 'tag2']);
      
    • Bulk Tagging: Tag multiple entities at once:
      $tagService->bulkTag([$entity1, $entity2], ['common-tag']);
      
  2. Querying Tags

    • Filter by Tag: Fetch entities tagged with a specific term:
      $tagService->findByTag('laravel', Post::class);
      
    • Autocomplete: Use TagService::autocomplete() for search-as-you-type functionality:
      $suggestions = $tagService->autocomplete('lar', 5); // Top 5 matches for 'lar'
      
  3. Tag Management

    • Create/Update Tags: The bundle auto-creates tags on first use. Customize behavior via TagService:
      $tagService->createTag('new-tag', ['slug' => 'custom-slug']);
      
    • Delete Tags: Remove tags safely (cascades to Tagging entities):
      $tagService->deleteTag($tag);
      

Integration Tips

  • Forms: Use Symfony’s EntityType with Tag for tag selection:
    $builder->add('tags', EntityType::class, [
        'class' => Tag::class,
        'multiple' => true,
        'expanded' => true,
    ]);
    
  • APIs: Expose tagging via API Platform or custom controllers:
    #[Route('/posts/{id}/tags', methods: ['POST'])]
    public function addTags(Post $post, Request $request): JsonResponse
    {
        $tags = json_decode($request->getContent(), true);
        $this->tagService->tag($post, $tags);
        return new JsonResponse(['status' => 'success']);
    }
    
  • Events: Listen for tagging events (e.g., TagAddedEvent) to trigger side effects:
    $dispatcher->addListener(TagAddedEvent::class, function (TagAddedEvent $event) {
        // Log or notify when tags are added
    });
    

Gotchas and Tips

Pitfalls

  1. Tag Ownership

    • Issue: Tags are not stored directly on taggable entities (unlike fpn/tag-bundle). This means:
      • No direct tags property on User or Post; use TagService to fetch tags.
      • Lazy-loading Tagging entities can cause N+1 queries. Use fetch: 'EAGER' or DQL joins:
        $query->leftJoin('tagging', 't', 'WITH', 't.tagged = :entity')
              ->where('t.tagged = :entity');
        
  2. Tagging Entity Requirements

    • Issue: Entities must implement TaggableInterface and include the TaggableTrait:
      use eduMedia\TagBundle\Entity\TaggableInterface;
      use eduMedia\TagBundle\Entity\TaggableTrait;
      
      class Post implements TaggableInterface
      {
          use TaggableTrait;
          // ...
      }
      
    • Fix: Forgetting this causes TagService to throw exceptions.
  3. Tagging Join Table

    • Issue: The Tagging entity’s tagged field must reference the primary key of the taggable entity (e.g., user.id). Misconfiguration breaks tagging.
    • Tip: Use TaggableTrait to auto-generate the tagged field correctly.
  4. Case Sensitivity

    • Issue: Tag names are case-sensitive by default. Use TagService::normalizeTag() to enforce consistency:
      $normalizedTag = $tagService->normalizeTag('Laravel'); // 'laravel'
      

Debugging

  • Check Tagging Links: Verify the Tagging entity’s tagged field points to the correct entity ID:
    $tagging = $entityManager->getRepository(Tagging::class)->findOneBy(['tag' => $tag]);
    dump($tagging->getTagged()->getId()); // Should match your entity's ID
    
  • Query Logs: Enable Doctrine debug mode to inspect queries:
    $entityManager->getConnection()->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger());
    
  • Event Listeners: Debug tagging events by dumping TagAddedEvent or TagRemovedEvent payloads.

Extension Points

  1. Custom Tag Storage

    • Override TagService to use a custom repository or cache layer:
      class CustomTagService extends TagService
      {
          public function getTags(object $taggable): array
          {
              // Custom logic (e.g., cache results)
              return parent::getTags($taggable);
          }
      }
      
    • Register the service in services.yaml:
      services:
          App\Service\CustomTagService: '@eduMedia\TagBundle\Service\TagService'
      
  2. Tag Validation

    • Extend TagInterface to add validation rules (e.g., max length):
      use Symfony\Component\Validator\Constraints as Assert;
      
      #[Assert\Length(max: 50)]
      protected string $name;
      
    • Use Symfony’s validator in forms or services.
  3. Tagging Strategies

    • Implement custom tagging logic (e.g., hierarchical tags) by extending TagService:
      public function tag(object $taggable, array $tags, string $strategy = 'default')
      {
          if ($strategy === 'hierarchical') {
              // Custom logic
          }
          parent::tag($taggable, $tags);
      }
      
  4. Performance

    • Batch Tagging: For bulk operations, use Doctrine’s BatchProcessing:
      $connection = $entityManager->getConnection();
      $connection->beginTransaction();
      // Bulk INSERT/UPDATE queries
      $connection->commit();
      
    • Indexing: Add database indexes to tagging.tagged and tagging.tag for faster queries:
      CREATE INDEX idx_tagging_tagged ON tagging(tagged);
      CREATE INDEX idx_tagging_tag ON tagging(tag);
      

Configuration Quirks

  • Doctrine Mappings: Ensure Tagging entity’s tagged field uses the correct type (e.g., string for UUIDs, integer for auto-increment IDs).
  • Symfony Cache: Clear cache after adding/removing tags if using cached TagService methods:
    php bin/console cache:clear
    
  • Translation: Tag names are not translatable by default. Use a TagTranslation entity or Symfony’s translation system for multilingual tags.
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