cvsouth/eloquent-inheritance

Laravel 的联合表继承

1.0.22 2022-02-07 23:51 UTC

README

安装

composer require cvsouth/eloquent-inheritance
php artisan migrate

用法

定义类

InheritableModel 继承模型而不是通常的 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;
    }
}

创建迁移时添加 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');
    }
}

存储对象

然后您可以使用对象就像普通的 Eloquent 对象一样

$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

查询对象

同样,您可以像通常的 Eloquent 一样查询对象

$bird = Bird::where("species", "=", "Aratinga solstitialis")->first();

$bird->speak();
// AAA!

不同继承级别的主键

在继承的每个级别,对象都有一个 id。在上面的示例中,$bird 有一个动物 id 以及一个鸟 id。此外,每个模型都有一个称为 base_id 的公共 id,它在整个类层次结构中是一致的。

使用 id_as 方法获取特定继承级别的模型 id

// The model's animal id
echo $bird->id_as(Animal::class);

// The model's bird id
echo $bird->id_as(Bird::class);

或使用 base_id 属性获取实体的基本 id

// The model's base id
echo $bird->base_id

关系

关系与常规 eloquent 关系类似,但请注意,您可以引用特定的继承级别。例如

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