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

Laravel Tagging Laravel Package

rtconner/laravel-tagging

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require rtconner/laravel-tagging
    php artisan vendor:publish --provider="Conner\Tagging\Providers\TaggingServiceProvider"
    php artisan migrate
    
    • Verify the tagging table exists in your database.
  2. First Use Case: Extend a model with the Taggable trait:

    use Conner\Tagging\Taggable;
    
    class Article extends Model
    {
        use Taggable;
    }
    
    • Now you can tag an Article instance:
    $article = new Article();
    $article->tag('laravel');
    $article->tag('php');
    $article->save();
    
  3. Where to Look First:

    • README: Focus on the "Usage" section for basic CRUD operations.
    • Migrations: Check database/migrations/ for the tagging table structure.
    • Model Methods: Explore the trait’s methods like tag(), untag(), tags(), etc.

Implementation Patterns

Core Workflows

  1. Tagging Models:

    // Add tags (creates or syncs)
    $model->tag('tag1')->tag('tag2')->save();
    
    // Sync tags (replaces existing)
    $model->syncTags(['tag1', 'tag2']);
    
    // Detach tags
    $model->untag('tag1');
    
  2. Querying Tagged Models:

    // Find models with a specific tag
    $articles = Article::tagged('laravel')->get();
    
    // Find models with multiple tags (AND logic)
    $articles = Article::tagged(['laravel', 'php'])->get();
    
    // Find models with any of these tags (OR logic)
    $articles = Article::whereAnyTag(['laravel', 'php'])->get();
    
  3. Tag Management:

    // Get all tags for a model
    $tags = $model->tags;
    
    // Get raw tag names (slugs)
    $tagNames = $model->tagNames;
    
    // Get tag count
    $count = $model->tagCount;
    
  4. Global Tag Operations:

    // Get all tags used in the system
    $allTags = \Conner\Tagging\Tag::all();
    
    // Find models tagged with a specific tag globally
    $models = \Conner\Tagging\Tag::findByName('laravel')->models;
    

Integration Tips

  1. Form Handling:

    • Use syncTags() in form submissions to avoid duplicate tags:
      $request->validate(['tags' => 'required|array']);
      $model->syncTags($request->tags);
      
  2. API Responses:

    • Serialize tags for JSON responses:
      return $model->load('tags')->toArray();
      
    • Or use a custom accessor:
      public function getTagsAttribute()
      {
          return $this->tags->pluck('name');
      }
      
  3. Admin Panels:

    • Use tagged() scopes to filter records in admin interfaces (e.g., Laravel Nova, Filament).
  4. Seeding:

    • Seed tagged models with syncTags():
      $article = Article::create(['title' => 'Test']);
      $article->syncTags(['seed', 'test']);
      
  5. Caching:

    • Cache frequent tag queries (e.g., popular tags):
      $popularTags = Cache::remember('popular-tags', now()->addHours(1), function () {
          return Tag::withCount('models')->orderBy('models_count', 'desc')->take(10)->get();
      });
      

Gotchas and Tips

Pitfalls

  1. Case Sensitivity:

    • Tags are case-insensitive due to slug transformation. "Laravel" and "laravel" are treated as the same tag.
    • Fix: Use Tag::findByName() with exact slugs if case sensitivity is required.
  2. Duplicate Tags:

    • tag() adds tags without checking for duplicates. Use syncTags() to avoid duplicates.
    • Fix: Validate input before tagging:
      $uniqueTags = array_unique($request->tags);
      $model->syncTags($uniqueTags);
      
  3. Performance with Large Datasets:

    • Scopes like tagged() can be slow on tables with millions of records.
    • Fix: Add database indexes to the tagging pivot table:
      Schema::table('tagging', function (Blueprint $table) {
          $table->index(['tag_id', 'taggable_id']);
      });
      
  4. Tag Deletion:

    • Deleting a tag does not automatically remove it from models. Use untag() or syncTags() to clean up.
    • Fix: Handle tag deletion carefully in your application logic.
  5. Model Polymorphism:

    • The package supports polymorphic relationships out of the box, but ensure your taggable column in the tagging table matches your models' morphKey.

Debugging

  1. Tag Not Found:

    • If tagged() returns no results, verify the tag slug exists in the tags table.
    • Debug: Run Tag::findByName('tag-slug')->toSql() to check the query.
  2. Pivot Table Issues:

    • If tags aren’t saving, check the tagging pivot table for errors.
    • Debug: Temporarily add dd($model->tags) after saving to inspect the relationship.
  3. Slug Conflicts:

    • Custom slug logic (e.g., in Tag::boot()) may cause conflicts.
    • Debug: Override the getSlugFromName() method if needed:
      use Conner\Tagging\Tag;
      
      class CustomTag extends Tag
      {
          public static function getSlugFromName($name)
          {
              return Str::slug($name, '-').'-custom';
          }
      }
      

Extension Points

  1. Custom Tag Model:

    • Extend the Tag model to add fields (e.g., color, description):
      class Tag extends Conner\Tagging\Tag
      {
          protected $casts = ['color' => 'string'];
      }
      
    • Update the migration and pivot table accordingly.
  2. Tag Validation:

    • Add validation rules to the Tag model:
      use Illuminate\Database\Eloquent\Model;
      
      class Tag extends Conner\Tagging\Tag
      {
          protected static function boot()
          {
            parent::boot();
            static::creating(function ($tag) {
                $tag->name = Str::title($tag->name);
            });
        }
      }
      
  3. Custom Scopes:

    • Add reusable scopes to the Taggable trait:
      use Conner\Tagging\Taggable;
      
      class Article extends Model
      {
          use Taggable;
      
          public function scopePopular($query)
          {
              return $query->whereHas('tags', function ($q) {
                  $q->orderBy('tags.created_at', 'desc');
              })->limit(10);
          }
      }
      
  4. Tag Events:

    • Listen for tag-related events (e.g., tagged, untagged):
      use Conner\Tagging\Events\Tagged;
      
      Tagged::listen(function ($model, $tag) {
          Log::info("Model {$model->id} was tagged with {$tag->name}");
      });
      
  5. Localization:

    • Localize tag names by overriding the getNameAttribute():
      public function getNameAttribute($value)
      {
          return __($value);
      }
      
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.
directorytree/privacy-filter-classifier
directorytree/privacy-filter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony
spatie/flare-daemon-runtime