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

rinvex/laravel-categories

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install & Publish:

    composer require rinvex/laravel-categories
    php artisan rinvex:publish:categories
    php artisan migrate
    
    • Focus on config/categories.php for core settings (e.g., model, sluggable, translatable).
    • Review the categories table structure (supports polymorphic relationships via categoryable table).
  2. First Use Case: Categorize a Model

    • Add traits to your Eloquent model:
      use Rinvex\Categories\Traits\HasCategories;
      use Rinvex\Categories\Traits\HasCategory;
      
    • Define relationships in your model:
      public function categories()
      {
          return $this->morphToMany(Category::class, 'categoryable');
      }
      
    • Attach categories to a model instance:
      $post = Post::find(1);
      $post->categories()->attach([1, 2]); // Attach by IDs
      
  3. Key Initial Commands:

    • php artisan rinvex:categories:seed (if using seeds).
    • php artisan rinvex:categories:make:model (for custom category models).

Implementation Patterns

Core Workflows

  1. Hierarchical Categories (Nested Sets)

    • Leverage lazychaser/laravel-nestedset for tree-like structures:
      $parent = Category::find(1);
      $child = $parent->children()->create(['name' => 'Subcategory']);
      
    • Query descendants/ancestors:
      $post->categories->whereHas('descendants'); // Posts in subcategories
      
  2. Polymorphic Categorization

    • Use HasCategories trait to categorize any model (e.g., Post, Product):
      $product = Product::find(1);
      $product->categories()->sync([3, 4]); // Sync replaces existing
      
    • Filter models by category:
      Post::whereHas('categories', function($q) {
          $q->where('name', 'Tech');
      })->get();
      
  3. Slugs & Translations

    • Auto-generate slugs with spatie/laravel-sluggable:
      use Sluggable;
      class Category extends Model {
          use Sluggable;
          public function getSlugOptions() { return ['source' => 'name']; }
      }
      
    • Translate category names with spatie/laravel-translatable:
      $category->setTranslations('name', [
          'en' => 'Electronics',
          'es' => 'Electrónicos'
      ]);
      
  4. API & Frontend Integration

    • Serialize categories with relationships:
      return Category::with('children')->get()->toJson();
      
    • Use rinvex/categories in Vue/React via API endpoints (e.g., /api/categories).

Advanced Patterns

  • Custom Category Models: Extend Rinvex\Categories\Models\Category for domain-specific logic.
  • Scoped Queries:
    $activeCategories = Category::active()->get(); // Uses `is_active` column
    
  • Events & Observers: Listen to CategoryCreated, CategoryDeleted events for side effects (e.g., cache updates).

Gotchas and Tips

Pitfalls

  1. Migration Conflicts:

    • If categories table exists, drop it before publishing new migrations.
    • Fix: php artisan migrate:fresh or manually resolve column conflicts.
  2. Polymorphic Relationships:

    • Forgetting to define categoryable table or using incorrect morph keys (e.g., categoryable_type/id).
    • Fix: Verify morphToMany setup:
      Schema::create('categoryable', function (Blueprint $table) {
          $table->unsignedBigInteger('category_id');
          $table->unsignedBigInteger('categoryable_id');
          $table->string('categoryable_type');
          $table->foreign('category_id')->references('id')->on('categories');
      });
      
  3. Nested Set Performance:

    • Deep category trees may slow queries. Use depth or path optimizations:
      Category::where('path', 'like', '1.2.%')->get(); // Subcategories of ID 2
      
  4. Slug Collisions:

    • Slugs may conflict if source isn’t unique. Use unique:categories,slug in validation.
    • Fix: Override getSlugOptions to include a counter:
      public function getSlugOptions() {
          return ['source' => 'name', 'unique' => true];
      }
      

Debugging Tips

  • Query Logging: Enable Laravel debug mode (APP_DEBUG=true) to inspect nested set queries.
  • Seeding Issues: Use php artisan rinvex:categories:seed --force to reset test data.
  • Translatable Fields: Ensure translations table exists and translated attribute is defined:
    protected $translatable = ['name', 'description'];
    

Extension Points

  1. Custom Validation: Override Category model rules:

    public static function boot() {
        parent::boot();
        static::addGlobalScope('active', function (Builder $builder) {
            $builder->where('is_active', true);
        });
    }
    
  2. API Resources: Extend Rinvex\Categories\Http\Resources\CategoryResource for custom fields.

  3. Service Providers: Bind custom category repositories:

    $this->app->bind(
        \Rinvex\Categories\Contracts\CategoryRepository::class,
        \App\Repositories\CustomCategoryRepository::class
    );
    
  4. Testing: Use rinvex/categories factories:

    $category = Category::factory()->create(['name' => 'Books']);
    $post->categories()->attach($category);
    

    Assert relationships:

    $this->assertCount(1, $post->categories);
    

Configuration Quirks

  • Default Model: Override config['model'] if not using Rinvex\Categories\Models\Category.
  • Slug Generation: Set config['sluggable']['source'] to control slug fields (e.g., title).
  • Translatable Locales: Define config['translatable']['locales'] for supported languages.

```markdown
## Performance Considerations
- **Eager Loading**: Always eager-load relationships to avoid N+1 queries:
  ```php
  Post::with('categories.children')->get();
  • Caching: Cache category trees if frequently accessed:
    Cache::remember('categories-tree', now()->addHours(1), function() {
        return Category::with('children')->get();
    });
    
  • Indexing: Add indexes to categoryable table for polymorphic queries:
    Schema::table('categoryable', function (Blueprint $table) {
        $table->index(['categoryable_type', 'categoryable_id']);
    });
    
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.
comsave/common
alecsammon/php-raml-parser
chrome-php/wrench
lendable/composer-license-checker
typhoon/reflection
mesilov/moneyphp-percentage
mike42/gfx-php
bookdown/themes
aura/view
aura/html
aura/cli
povils/phpmnd
nayjest/manipulator
omnipay/tests
psr-mock/http-message-implementation
psr-mock/http-factory-implementation
psr-mock/http-client-implementation
voku/email-check
voku/urlify
rtheunissen/guzzle-log-middleware