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

lecturize/laravel-taxonomies

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require lecturize/laravel-taxonomies
    php artisan vendor:publish --provider="Lecturize\Taxonomies\TaxonomiesServiceProvider"
    php artisan migrate
    

    Ensure database/migrations is in composer.json classmap.

  2. First Use Case: Attach the HasCategories trait to a model (e.g., Post):

    use Lecturize\Taxonomies\Traits\HasCategories;
    
    class Post extends Model
    {
        use HasCategories;
    }
    

    Run migrations and test with:

    php artisan migrate:fresh
    
  3. Quick Taxonomy Creation: Define a taxonomy in a migration or via Tinker:

    use Lecturize\Taxonomies\Models\Taxonomy;
    
    Taxonomy::create(['name' => 'post_categories']);
    

Implementation Patterns

Core Workflows

  1. Model Integration:

    • Use HasCategories for basic taxonomy support.
    • For custom taxonomies, implement CanHaveCategories contract:
      class Post extends Model implements CanHaveCategories
      {
          public function getTaxonomies(): array
          {
              return ['post_categories'];
          }
      }
      
  2. Term Management:

    • Create terms via:
      $post->categories()->sync([1, 2, 3]); // Sync with existing terms
      $post->categories()->create(['name' => 'New Category']); // Create new
      
    • Nest terms (parent-child relationships):
      $parent = Term::find(1);
      $child = $parent->children()->create(['name' => 'Subcategory']);
      
  3. Querying:

    • Filter models by taxonomy terms:
      $posts = Post::withCategories(['post_categories' => [1, 2]])->get();
      
    • Get terms for a model:
      $terms = $post->getTerms('post_categories');
      
  4. Slugs & SEO:

    • Leverage EloquentSluggable (published via package) for automatic slugs:
      class Term extends Model
      {
          use \Cviebrock\EloquentSluggable\Sluggable;
      
          public function getSlugOptions()
          {
              return ['source' => 'name'];
          }
      }
      
  5. API/JSON Responses:

    • Serialize taxonomies with toArray() or toJson():
      $post->load('categories');
      return $post->toJson();
      

Gotchas and Tips

Pitfalls

  1. Migration Classmap:

    • Forgetting to add database/migrations to composer.json classmap will break migrations. Fix:
      "autoload": {
          "classmap": ["database/migrations"]
      }
      
  2. Term Sync Behavior:

    • sync() detaches all terms not in the given array. Use attach() to add without detaching:
      $post->categories()->attach([4, 5]); // Adds without detaching others
      
  3. Nested Term Queries:

    • Deeply nested terms may cause N+1 queries. Use with():
      $terms = Term::with('children')->find(1);
      
  4. Taxonomy Validation:

    • Ensure getTaxonomies() returns an array of string taxonomy names (not IDs or models).
  5. Slug Conflicts:

    • Customize slug generation to avoid collisions (e.g., append IDs):
      public function getSlugOptions()
      {
          return ['source' => 'name', 'onUpdate' => true];
      }
      

Debugging

  • Term Not Found?: Verify the taxonomy name matches exactly (case-sensitive) in getTaxonomies(). Check if the term exists in the terms table.

  • Relationship Errors: Ensure the pivot table exists (e.g., taxonomy_term_model for Post and post_categories).

Extension Points

  1. Custom Pivot Tables: Override pivot table names in the HasCategories trait:

    protected $taxonomyPivotTable = 'custom_pivot_name';
    
  2. Term Scopes: Add global scopes to Term model for reusable queries:

    class TermScope extends Scope
    {
        public function apply(Builder $builder, $taxonomy)
        {
            $builder->where('taxonomy', $taxonomy);
        }
    }
    
  3. Event Listeners: Listen for term creation/deletion:

    Term::created(function ($term) {
        // Log or notify
    });
    
  4. API Resources: Extend TaxonomyResource or TermResource for custom JSON structures:

    class CustomTermResource extends Resource
    {
        public function toArray($request)
        {
            return [
                'id' => $this->id,
                'name' => $this->name,
                'slug' => $this->slug,
                'path' => $this->getPath(), // Custom method
            ];
        }
    }
    

Performance Tips

  • Eager Load Terms: Always use with() to avoid N+1 queries:

    $posts = Post::with(['categories' => function ($query) {
        $query->where('taxonomy', 'post_categories');
    }])->get();
    
  • Cache Taxonomies: Cache taxonomy lists if rarely changed:

    $taxonomies = Cache::remember('taxonomies', 60, function () {
        return Taxonomy::all()->pluck('name');
    });
    
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.
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
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope