Taner Arar
Taner Arar

Reputation: 1

How to establish a dynamic model relationship in Laravel?

I need to establish a dynamic relationship but I can't.

The table design is as follows.

Page Table

id title
1 Hello world
2 Contact

Category Table

id title
1 Electronics
2 Sports

Blog Table

id title
1 First blog

Links Type

id name
1 Page
2 Category
3 Blog

Links Table

id type_id relation_id slug
1 1 1 page/hello-world
2 1 2 page/contact
3 2 1 category/electronics
3 2 2 category/sports
3 3 1 blog/first-blog

CODE

Controller:

$links = Links::with('title')->get();

return response()->json($links);

// I need to get the "title" key.

Links Model:

public function title() {
    switch($this->type_id) {
        case '1':
            return $this->hasOne(Page::class, 'id', 'relation_id');
            break;
        case '2':
            return $this->hasOne(Category::class, 'id', 'relation_id');
            break;
        case '3':
            return $this->hasOne(Blog::class, 'id', 'relation_id');
            break;
    }
}

This state does not work because the model has not yet been formed.

Error Output

Call to a member function addEagerConstraints() on null

How should I go about it?

Thanks.

Upvotes: 0

Views: 955

Answers (1)

IGP
IGP

Reputation: 15786

What you are doing can be achieved by using polymorphic relationships.

pages
    id - integer
    name - string

categories
    id - integer
    title - string

blogs
    id - integer
    title - string

link_types
    id - integer
    name - string

links
    id - integer
    link_type_id - integer
    linkable_id - integer
    linkable_type - string

Page, Category and Blog model should define these relationships

public function link_types()
{
    return $this->morphToMany(LinkType::class, 'linkable', 'links')->using(Link::class);
}

public function links()
{
    return $this->morphMany(Link::class, 'linkable')
}

LinkType model should define these relationships

public function pages()
{
    return $this->morphedByMany(Page::class, 'linkable', 'links')->using(Link::class);
}

public function categories()
{
    return $this->morphedByMany(Category::class, 'linkable', 'links')->using(Link::class);
}

public function blogs()
{
    return $this->morphedByMany(Blog::class, 'linkable', 'links')->using(Link::class);
}

Link model should define these relationships

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Relations\MorphPivot;

class Link extends MorphPivot
{
    /**
     * Get the parent linkable model (blog, category, page).
     */
    public function linkable()
    {
        return $this->morphTo();
    }

    public function link_type()
    {
        return $this->belongsTo(LinkType::class, 'link_type_id');
    }
}
$link = Link::with('linkable')->first();

$link->linkable->title;

Upvotes: 1

Related Questions