cvsouth / eloquent-inheritance
Joined-table inheritance for Laravel
This package's canonical repository appears to be gone and the package has been frozen as a result.
Installs: 2 676
Dependents: 0
Suggesters: 0
Security: 0
Stars: 12
Watchers: 4
Forks: 3
Open Issues: 1
Requires
- doctrine/dbal: ^2.10|^3.3
- illuminate/database: ^8.4|^9.0
- illuminate/support: ^7.0|^8.0|^9.0
README
Installation
composer require cvsouth/eloquent-inheritance
php artisan migrate
Usage
Defining classes
Extend your models from InheritableModel
instead of the usual Model
:
class Animal extends InheritableModel { public $table = "animals"; protected $fillable = [ 'name', 'species', ]; public function speak() { print($this->name . ' makes a noise'); } }
class Bird extends Animal { public $table = "birds"; protected $fillable = [ 'flying', ]; public function speak() { print('AAA!'); } public function fly() { $this->flying = true; } public function land() { $this->flying = false; } public function isFlying() { return $this->flying; } }
When creating your migrations add base_id
:
class CreateAnimalsTable extends Migration { public function up() { Schema::create('animals', function (Blueprint $table) { $table->bigIncrements('id'); $table->bigInteger('base_id')->unsigned(); $table->string('species', 250); $table->string('name', 250)->nullable(); }); } public function down() { Schema::drop('animals'); } }
class CreateBirdsTable extends Migration { public function up() { Schema::create('birds', function (Blueprint $table) { $table->bigIncrements('id'); $table->bigInteger('base_id')->unsigned(); $table->boolean('flying')->default(false); }); } public function down() { Schema::drop('birds'); } }
Storing objects
You can then use your objects just like normal Eloquent objects:
$bird = new Bird ([ "species" => "Aratinga solstitialis", // Note: This attribute is inherited from Animal ]); $bird->fly(); echo "This " . strtolower($bird->species) . " is " . ($bird->isFlying() ? "" : "not ") . "flying" . '<br/>'; // This aratinga solstitialis is flying $bird->species = 'Sun Conure'; $bird->save(); $bird->land(); echo "This " . strtolower($bird->species) . " is " . ($bird->isFlying() ? "" : "not ") . "flying" . '<br/>'; // This sun conure is not flying
Querying objects
Again, you can query the object just like usual for Eloquent:
$bird = Bird::where("species", "=", "Aratinga solstitialis")->first(); $bird->speak(); // AAA!
Primary keys at different levels of inheritance
At each level of inheritance the object has an id. In the example above, the $bird has an animal id as well as a bird id In addition to this each model has a common id called base_id
which is consistent throughout it's class hierarchy.
Use the id_as
method to get the id for a model at a specific level of inheritance:
// The model's animal id echo $bird->id_as(Animal::class); // The model's bird id echo $bird->id_as(Bird::class);
Or use the base_id
property to get the entities base id:
// The model's base id echo $bird->base_id
Relationships
Relationships work like regular eloquent relationships but bear in mind that you can reference specific levels of inheritance. For example:
class Trainer extends InheritableModel { public $table = "trainers"; protected $fillable = [ 'name', 'animal_id', ]; public function animal() { return $this->belongsTo(Animal::class); } }
class CreateTrainersTable extends Migration { public function up() { Schema::create('trainers', function (Blueprint $table) { $table->bigIncrements('id'); $table->bigInteger('base_id')->unsigned(); $table->string('name', 250)->nullable(); $table->bigInteger('animal_id')->unsigned(); }); Schema::table('trainers', function ($table) { $table->foreign('animal_id')->references('id')->on('animals')->onDelete('cascade'); }); } public function down() { Schema::drop('trainers'); } }
$bird = Bird::where("species", "=", "Aratinga solstitialis")->first(); $trainer = new Trainer ([ "name" => "Trainer 1", "animal_id" => $bird->id_as(Animal::class), // Reference the bird's Animal ID ]); $trainer->save(); echo class_basename($trainer->animal); // Bird echo $trainer->animal->species; // Sun Conure