Multi-table inheritance in Laravel

1

I have a Resource entity, which in turn has several implementations, for example, VideoResource and MarkdownResource . Resource has several shared properties, the other two examples in turn have specific properties for them.

I've seen about inheritance using single-table , but I believe that this can not be my case, since I can have multiple implementations of Resource and each implementation can have 2 a 5 specific properties .

How to make this type of relationship with Eloquent ?

    
asked by anonymous 20.02.2018 / 03:29

1 answer

1

The form that was created to work with this type of relationship is Polymorphic Relations , in question was just informed the names of the tables that is enough to create a minimal example:

Migration:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class TableVideoResources extends Migration
{    
    public function up()
    {
        Schema::create('videoresources', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title', 50);
            $table->timestamps();
        });
    }
    public function down()
    {
        Schema::dropIfExists('videoresources');
    }
}
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class TableResources extends Migration
{    
    public function up()
    {
        Schema::create('resources', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name', 50);
            $table->timestamps();
            $table->integer('resourceable_id')->unsigned(); 
            $table->string('resourceable_type', 100);
        });
    }
    public function down()
    {
        Schema::dropIfExists('resources');
    }
}

Class Model:

<?php namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Resource extends Model
{
    protected $primaryKey = 'id';
    protected $table = 'resources';
    protected $fillable = ['name'];
    public $timestamps = true;    

    public function resourceable()
    {
        return $this->morphTo();
    }
}
<?php namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class VideoResource extends Model
{
    protected $primaryKey = 'id';
    protected $table = 'videoresources';
    protected $fillable = ['title'];
    public $timestamps = true;    

    public function resource()
    {
        return $this->morphOne(Resource::class, 'resourceable');
    }
}

that is, the VideoResource class has been set to have a relation with Resource , dividing there the data that is different to VideoResource and the other classes that inherit what is equal must be set equal VideoResource (in your question besides VideoResource has MarkdownResource ). But there is not much magic in it all, for example to save the relationship must first create VideoResource and access the relationship and create Resource , eg:

Recording VideoResource :

$videoResource = App\Models\VideoResource::create(['title' => 'Stackoverflow']);

Writing Resource by relation:

$videoResource->resource()->create(['name' => 'Portugues Brasil']);

to retrieve information:

App\Models\VideoResource::with('resource')->find(3);

Output:

=> App\Models\VideoResource {#787                       
     id: 3,                                             
     title: "Stackoverflow",                            
     created_at: "2018-02-22 14:27:39",                 
     updated_at: "2018-02-22 14:27:39",                 
     resource: App\Models\Resource {#793                
       id: 3,                                           
       name: "Portugues Brasil",                        
       created_at: "2018-02-22 14:29:57",               
       updated_at: "2018-02-22 14:29:57",               
       resourceable_id: 3,                              
       resourceable_type: "App\Models\VideoResource",   
     },                                                 
   }                                                    

you can check all this in the documentation and in this minimal example .

References:

22.02.2018 / 15:23