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

oleaass/laravel-categories

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require oleaass/laravel-categories
    

    Publish the migration (if needed) and run:

    php artisan migrate
    
  2. Model Setup: Add the Categorizable trait to your model (e.g., Product):

    use OleAass\Categories\Categorizable;
    
    class Product extends Model
    {
        use Categorizable;
    }
    
  3. First Use Case: Attach a category to a model instance:

    $product = Product::find(1);
    $product->categories()->attach(1); // Attach category ID 1
    

    Retrieve categories for a model:

    $categories = $product->categories; // Collection of Category models
    

Where to Look First

  • Migration: Check database/migrations/ for the categories and categoryables tables.
  • Category Model: Default Category model is auto-discovered (located in vendor/oleaass/laravel-categories/src/Models/Category.php).
  • Facade: Use Category:: for helper methods (e.g., Category::create(['name' => 'Electronics'])).

Implementation Patterns

Core Workflows

  1. CRUD for Categories:

    // Create
    $category = Category::create(['name' => 'Books']);
    
    // Read
    $categories = Category::all();
    
    // Update
    $category->update(['name' => 'Updated Books']);
    
    // Delete
    $category->delete();
    
  2. Polymorphic Relationships: Attach categories to any model (e.g., Product, Article):

    class Article extends Model
    {
        use Categorizable;
    }
    
    $article = Article::find(1);
    $article->categories()->attach([1, 2]); // Attach multiple categories
    
  3. Scopes and Querying: Filter models by category:

    $products = Product::withCategories([1, 2])->get(); // Products in categories 1 or 2
    $products = Product::inCategory(1)->get(); // Products in category 1 (uses scope)
    
  4. Hierarchical Categories (Optional): If extending for parent-child relationships, override the Category model:

    class Category extends \OleAass\Categories\Models\Category
    {
        public function children()
        {
            return $this->hasMany(self::class, 'parent_id');
        }
    }
    

Integration Tips

  • Validation: Use Laravel’s validation rules for category names:
    use Illuminate\Support\Facades\Validator;
    
    $validator = Validator::make(['name' => ''], [
        'name' => 'required|string|max:255|unique:categories',
    ]);
    
  • API Resources: Transform categories in API responses:
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'products_count' => $this->products->count(), // Polymorphic relation
        ];
    }
    
  • Caching: Cache category lists if frequently accessed:
    $categories = Cache::remember('all_categories', now()->addHours(1), function () {
        return Category::all();
    });
    

Gotchas and Tips

Pitfalls

  1. Polymorphic Table Naming: The pivot table (categoryables) uses Laravel’s default naming convention. If you customize pivot table names elsewhere, ensure consistency:

    // In Category model (if overriding)
    public function categoryables()
    {
        return $this->morphToMany('categoryable', 'categoryables', 'category_id', 'categoryable_id', 'categoryable_type');
    }
    
  2. Model Binding: Avoid binding polymorphic models directly to category routes without checking the categoryable_type:

    // Risky: Assumes all categoryables are Products
    Route::get('/categories/{category}/products', function (Category $category) {
        return $category->products; // Fails if categoryable_type is 'Article'
    });
    

    Fix: Use explicit queries:

    $products = Product::whereHas('categories', fn ($q) => $q->where('categories.id', $category->id))->get();
    
  3. Mass Assignment: Enable fillable in the Category model if using create() with arrays:

    protected $fillable = ['name', 'slug', 'description'];
    
  4. Migration Conflicts: If the categories table already exists, manually adjust the migration or drop it first:

    php artisan migrate:fresh --env=testing
    

Debugging

  • Missing Categories: Check if the Categorizable trait is correctly used and the pivot table exists:
    php artisan schema:dump
    
  • Polymorphic Errors: Verify categoryable_type and categoryable_id are set in the pivot table:
    SELECT * FROM categoryables WHERE categoryable_type = 'App\Models\Product';
    
  • Soft Deletes: If using soft deletes, ensure the Category model has the SoftDeletes trait and the deleted_at column exists.

Extension Points

  1. Custom Category Model: Extend the default Category model:

    namespace App\Models;
    
    use OleAass\Categories\Models\Category as BaseCategory;
    
    class Category extends BaseCategory
    {
        protected $table = 'custom_categories';
        public $timestamps = false;
    }
    

    Update the service provider to bind your custom model:

    $this->app->bind('category', function () {
        return new \App\Models\Category();
    });
    
  2. Custom Pivot Table: Override the pivot table name in the Categorizable trait:

    public function categories()
    {
        return $this->morphToMany(
            config('categories.model'),
            'category',
            'custom_categoryables',
            'categoryable_id',
            'category_id',
            'categoryable_type'
        );
    }
    
  3. Events: Listen for category-related events (e.g., CategoryCreated):

    use OleAass\Categories\Events\CategoryCreated;
    
    CategoryCreated::dispatch($category);
    

    Register listeners in EventServiceProvider:

    protected $listen = [
        CategoryCreated::class => [
            \App\Listeners\LogCategoryCreation::class,
        ],
    ];
    
  4. API Resources: Create a dedicated CategoryResource for consistent API responses:

    namespace App\Http\Resources;
    
    use Illuminate\Http\Resources\Json\JsonResource;
    
    class CategoryResource extends JsonResource
    {
        public function toArray($request)
        {
            return [
                'id' => $this->id,
                'name' => $this->name,
                'models_count' => $this->categoryables()->count(),
                'models' => $this->categoryables, // Polymorphic collection
            ];
        }
    }
    
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.
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
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