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

mannikj/laravel-sti

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require mannikj/laravel-sti
    

    No additional configuration is required beyond publishing the trait.

  2. Migration: Add the sti() macro to your table migration:

    Schema::create('items', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->sti()->nullable(); // Adds 'type' column with nullable constraint
    });
    
  3. First Use Case: Define a root model with the trait and child models:

    use MannikJ\Laravel\SingleTableInheritance\Traits\SingleTableInheritance;
    
    class Item extends Model {
        use SingleTableInheritance;
    }
    
    class Book extends Item {}
    class Movie extends Item {}
    

    Now, when querying Item::all(), instances will automatically resolve to Book or Movie based on the type column.


Implementation Patterns

Workflows

  1. Polymorphic Queries: Use whereType() to filter by child class:

    $books = Item::whereType(Book::class)->get(); // Returns only Book instances
    
  2. Dynamic Model Resolution: The trait handles instantiation automatically. No need for manual resolveClass() calls.

  3. Scopes for Child Classes: Add class-specific scopes to child models:

    class Book extends Item {
        public function scopePublished($query) {
            return $query->where('published_at', '<=', now());
        }
    }
    

    Usage:

    $publishedBooks = Book::published()->get();
    
  4. Mass Assignment: Ensure type is not mass-assignable unless explicitly allowed:

    protected $guarded = ['type'];
    

Integration Tips

  • API Responses: Use getClass() to dynamically determine response formatting:

    return response()->json([
        'type' => $item->getClass(),
        'data' => $item->toArray(),
    ]);
    
  • Validation: Validate child-specific fields in child models:

    class Book extends Item {
        public function rules() {
            return [
                'isbn' => 'required|string',
            ];
        }
    }
    
  • Relationships: Define polymorphic relationships where needed:

    class User extends Model {
        public function items() {
            return $this->morphToMany([Book::class, Movie::class], 'itemable');
        }
    }
    

Gotchas and Tips

Pitfalls

  1. Missing type Column: If the type column is missing or misnamed, queries will fail silently or return incorrect model types. Always verify migrations.

  2. Case Sensitivity: The type column stores fully qualified class names (e.g., App\Models\Book). Ensure your database collation handles case sensitivity if using custom class names.

  3. Circular Dependencies: Avoid circular inheritance (e.g., A extends B extends A). Laravel’s STI does not enforce this, but it will cause runtime errors.

  4. Serialization: Serialized models (e.g., cached data) may not resolve correctly if class names change. Use getClass() to reconstruct instances safely.

Debugging

  • Incorrect Model Resolution: Check the type column value in the database. It must match the fully qualified class name (e.g., App\Models\Book).

    SELECT type FROM items WHERE id = 1;
    
  • Query Logs: Enable query logging to verify STI behavior:

    DB::enableQueryLog();
    $items = Item::all();
    dd(DB::getQueryLog());
    

Extension Points

  1. Custom Type Column: Override the getStiType() method in the root model:

    class Item extends Model {
        use SingleTableInheritance;
    
        public function getStiType(): string {
            return 'custom_type_column';
        }
    }
    
  2. Dynamic Class Resolution: Extend the trait to add custom logic:

    class Item extends Model {
        use SingleTableInheritance;
    
        protected static function resolveClass($value) {
            return match ($value) {
                'legacy_book' => LegacyBook::class,
                default => parent::resolveClass($value),
            };
        }
    }
    
  3. Soft Deletes: Ensure child models also use SoftDeletes if the root model does:

    use Illuminate\Database\Eloquent\SoftDeletes;
    
    class Book extends Item {
        use SoftDeletes;
    }
    

Performance

  • Index the type Column: Add an index for large tables to speed up whereType() queries:

    Schema::table('items', function (Blueprint $table) {
        $table->index('type');
    });
    
  • Avoid N+1 Queries: Use with() or load() for relationships to prevent eager-loading issues:

    $books = Book::with('author')->get();
    
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.
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
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