Multi-table heritage in Laravel

Asked

Viewed 407 times

2

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

I’ve seen about inheritance using single-table, but I believe it cannot be my case, as I may have several implementations of Resource and each implementation may have to 2 to 5 specific properties.

How to make that kind of relationship with Eloquent?

1 answer

2


The way it was created to work with this type of relationship is Polymorphic Relations, in the question only the name of the tables was informed which is enough to create a minimum 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 class VideoResource was configured to have a relationship with Resource, dividing there the data that are different for VideoResource and the other classes that inherit what is equal should be set equal VideoResource (in your question besides VideoResource has MarkdownResource). But there is not much magic in all this, for example to save the relationship you must first create VideoResource and access the relationship and create the Resource, example:

Recording VideoResource:

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

Recording Resource by the relationship:

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

to retrieve the information:

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

Exit:

=> 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 minimum example.

References:

  • 1

    I had already forgotten the question, I tried to solve it and I got it exactly in the way explained. Here is the repository implementing the already solved problem: https://github.com/lykeios-io/lykeios

Browser other questions tagged

You are not signed in. Login or sign up in order to post.