/eloquent-sti

Single Table Inheritance for Laravel's Eloquent ORM

Primary LanguagePHPMIT LicenseMIT

Eloquent Single Table Inheritance

Built For Laravel Build Status StyleCI Latest Version on Packagist Total Downloads Software License

Single Table Inheritance for Laravel's Eloquent ORM.

Install

Via Composer

$ composer require jonnypickett/eloquent-sti

After updating composer, add the ServiceProvider to the providers array in config/app.php

JonnyPickett\EloquentSTI\ServiceProvider::class,

Usage

Use the SingleTableInheritance trait in any Eloquent model to take advantage of Single Table Inheritance in Laravel with the model's subclasses.

A table taking advantage of Single Table Inheritance needs to store subclass names. By default, this package uses a field named subclass_name, so add this field, or the field name you choose (configuration is shown later), to your table.

Schema::table('animals', function(Blueprint $table)
{
    $table->string('subclass_name');
}

Once this field is added to your database table, you will need to add the SingleTableInheritance trait, make sure to specify the table property, and add the subclass name field to the $fillable array all on the parent model definition

class Animal extends Model
{
    use SingleTableInheritance;
    
    protected $table = 'animals';
    
    protected $fillable = [
        'subclass_name',
        ...
    ];
    
    protected $noise = '';
    
    /**
     * @return string
     */
    public function speak()
    {
        return $this->noise;
    }
}

Now just extend the parent model with any child models

class Dog extends Animal
{
    protected $noise = 'ruff';
}
    
class Cat extends Animal
{
    protected $noise = 'meow';
}

That's it. Now the entries in your table, animals for our example, will always be returned as an instance of a specific subclass. When retrieving a collection, the collection will be a collection of various subclass instances.

Configuration

By default, the subclass names will be stored in a field named subclass_name. This can be changed project wide by updating your .env file

ELOQUENT_STI_SUBCLASS_FIELD=your_subclass_field_name_here

or publishing and updating the package configuration file in app/config/eloquent-sti.php

php artisan vendor:publish --provider="JonnyPickett\EloquentSTI\ServiceProvider"
<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Default Subclass Field
    |--------------------------------------------------------------------------
    |
    | Subclass class names will be stored and retrieved from this field.
    | This can be overridden in specific classes by setting the
    | protected property $subclassFiled to a different value
    | in the class definition.
    |
    */

    'subclass_field' => env('ELOQUENT_STI_SUBCLASS_FIELD', 'your_subclass_field_name_here'),
];

or can be changed on a per model basis by adding a $subclassField property to your parent model

class Animal extends Model
{
    protected $subclassField = 'your_subclass_field_name_here'
}

Credit

Inspiration for this package came way back when I came across this Laravel.io forum post by Shawn McCool

License

The MIT License (MIT). Please see License File for more information.