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

aliziodev/laravel-taxonomy

Flexible Laravel package for managing taxonomies, categories, tags, and hierarchical trees. Includes nested-set support for fast hierarchy queries, metadata, bulk operations, caching, and custom taxonomy types. Compatible with Laravel 11+.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require aliziodev/laravel-taxonomy
    php artisan taxonomy:install
    php artisan migrate
    
  2. Add Trait to Model:

    use Aliziodev\LaravelTaxonomy\Traits\HasTaxonomy;
    
    class Product extends Model
    {
        use HasTaxonomy;
    }
    
  3. First Use Case:

    // Create a taxonomy
    $electronics = Taxonomy::create([
        'name' => 'Electronics',
        'type' => \Aliziodev\LaravelTaxonomy\Enums\TaxonomyType::Category->value,
    ]);
    
    // Attach to a model
    $product = Product::create(['name' => 'Laptop']);
    $product->attachTaxonomies($electronics->id);
    

Where to Look First

  • Facade: Taxonomy facade for direct taxonomy operations.
  • Model Methods: HasTaxonomy trait methods for model relationships.
  • Query Scopes: Built-in scopes for filtering models by taxonomies.
  • Documentation: Basic Usage section for quick reference.

Implementation Patterns

Core Workflows

1. Hierarchical Taxonomy Management

// Create parent-child relationships
$parent = Taxonomy::create(['name' => 'Parent', 'type' => TaxonomyType::Category->value]);
$child = Taxonomy::create([
    'name' => 'Child',
    'type' => TaxonomyType::Category->value,
    'parent_id' => $parent->id,
]);

// Get hierarchical tree
$tree = Taxonomy::tree(TaxonomyType::Category);

// Move a taxonomy (reparent)
$child->moveTo($parent->id);

2. Polymorphic Relationships

// Attach taxonomies to multiple model types
$product->attachTaxonomies([$electronics->id, $featured->id]);
$article->attachTaxonomies([$technology->id]);

// Query models by taxonomy
$products = Product::withTaxonomySlug('electronics')->get();
$articles = Article::withTaxonomySlug('technology')->get();

3. Bulk Operations

// Sync taxonomies (replace existing)
$product->syncTaxonomies([$electronics->id, $laptops->id]);

// Toggle taxonomies (add if missing, remove if present)
$product->toggleTaxonomies([$discount->id]);

4. Metadata Handling

// Store metadata with taxonomies
$category = Taxonomy::create([
    'name' => 'Books',
    'type' => TaxonomyType::Category->value,
    'meta' => [
        'icon' => 'book',
        'color' => '#3498db',
        'featured' => true,
    ],
]);

// Access metadata
$icon = $category->meta->icon;

5. Querying with Hierarchy

// Get all descendants of a taxonomy
$descendants = Taxonomy::getDescendants($electronics->id);

// Filter models by taxonomy hierarchy
$products = Product::withTaxonomyHierarchy($electronics->id)->get();

Integration Tips

1. Custom Taxonomy Types

Extend the default types in config/taxonomy.php:

'types' => [
    'category',
    'tag',
    'brand',
    'collection',
    'custom_type', // Add your custom type
],

2. Custom Slug Generation

Override slug generation in a service provider:

use Aliziodev\LaravelTaxonomy\Events\GeneratingSlug;

GeneratingSlug::macro('custom', function ($name, $type) {
    return Str::slug($name . '-' . $type);
});

3. Caching Strategies

Leverage Laravel's cache for performance:

// Cache taxonomy trees
Cache::remember('taxonomy-tree-' . $type, now()->addHours(1), function () use ($type) {
    return Taxonomy::tree($type);
});

4. API Responses

Format taxonomy data for APIs:

$taxonomy->toArray([
    'id', 'name', 'slug', 'type',
    'meta' => function () {
        return $this->meta;
    },
    'children' => function () {
        return $this->children()->with('children')->get();
    },
]);

5. Admin Panel Integration

Use the tree() method to render nested menus:

@foreach(Taxonomy::tree(TaxonomyType::Category) as $category)
    <li>
        {{ $category->name }}
        @if($category->children->count())
            <ul>
                @include('taxonomy.menu', ['categories' => $category->children])
            </ul>
        @endif
    </li>
@endforeach

Gotchas and Tips

Pitfalls

1. Slug Uniqueness

  • Issue: Slugs are unique per type, not globally (since v2.3.0).
    // This is allowed:
    Taxonomy::create(['name' => 'Featured', 'slug' => 'featured', 'type' => 'category']);
    Taxonomy::create(['name' => 'Featured', 'slug' => 'featured', 'type' => 'tag']);
    
  • Fix: Ensure your queries specify the type when filtering by slug:
    // Correct:
    Product::withTaxonomySlug('featured', TaxonomyType::Category)->get();
    

2. Nested Set Queries

  • Issue: Deep hierarchies may cause performance issues with nested set queries.
  • Fix: Use flatTree() for large hierarchies or limit depth:
    Taxonomy::flatTree(TaxonomyType::Category)->whereDepth('<=', 3);
    

3. Migration Autoloading

  • Issue: Migrations may run unexpectedly in multi-tenant apps.
  • Fix: Disable autoloading in config/taxonomy.php:
    'migrations' => [
        'autoload' => false,
    ],
    

4. Polymorphic Key Mismatch

  • Issue: Using morph_type: 'uuid' with integer IDs causes errors.
  • Fix: Ensure consistency in config/taxonomy.php:
    'morph_type' => 'numeric', // For integer IDs
    // or
    'morph_type' => 'uuid',   // For UUID IDs
    

5. Caching Invalidation

  • Issue: Cached taxonomy data may not update immediately.
  • Fix: Manually invalidate cache after updates:
    Cache::forget('taxonomy-tree-' . $type);
    

Debugging Tips

1. Query Logging

Enable query logging to debug nested set queries:

DB::enableQueryLog();
$tree = Taxonomy::tree(TaxonomyType::Category);
dd(DB::getQueryLog());

2. Hierarchy Validation

Validate hierarchy integrity:

// Check if a taxonomy is a descendant
$isDescendant = Taxonomy::isDescendant($childId, $parentId);

// Get path to root
$path = Taxonomy::getPath($taxonomyId);

3. Bulk Operation Debugging

Log bulk operations to avoid silent failures:

$product->syncTaxonomies([$electronics->id, $laptops->id], true); // Force sync

4. Slug Generation

Debug slug conflicts:

// Check if slug exists for a type
$exists = Taxonomy::where('slug', 'featured')
    ->where('type', TaxonomyType::Category->value)
    ->exists();

Extension Points

1. Custom Taxonomy Model

Extend the base Taxonomy model:

class CustomTaxonomy extends \Aliziodev\LaravelTaxonomy\Models\Taxonomy
{
    protected $casts = [
        'meta' => 'array',
        'is_active' => 'boolean',
    ];

    public function scopeActive($query)
    {
        return $query->where('is_active', true);
    }
}

Update config/taxonomy.php:

'model' => App\Models\CustomTaxonomy::class,

2. Custom Query Scopes

Add scopes to filter taxonomies:

use Illuminate\Database\Eloquent\Builder;

class Taxonomy extends \Aliziodev\LaravelTaxonomy\Models\Taxonomy
{
    public function scopeFeatured($query)
    {
        return $query->where('meta->featured', true);
    }
}

3. Event Listeners

Listen to taxonomy events:

Taxonomy::created(function ($taxonomy) {
    // Log creation
    \Log::info("Taxonomy created: {$taxonomy->name}");
});

Taxonomy::deleted(function ($taxonomy) {
    // Clean up related data
    $taxonomy->taxonomables()->delete();
});

4. Custom Tree Representation

Override

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.
nasirkhan/laravel-sharekit
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