Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define relationships when using interfaces

The normal use of polymorphic relationships in Laravel is covered pretty well by the Post--User--Image example.

I'm trying to find a clean way to implement relationships for let's say an Article/ContentA/ContentB relationship.

articles
  id

content_1
  id

content_2
  id

user_defined_content_n
  id

contentables
  article_id
  contentable_id
  contentable_type // content_2, user_defined_content_n

The content classes are not necessarily known by the article, so defining the article model with many MorphedByMany relationships is not how I want to do this.

Perhaps I am structuring my classes poorly. I could create a ContentEntity class which morphs to individual Content classes but I would like to avoid this if possible.


Maybe this better explains my problem.

class Article extends Model {
    public function contentEntities() {
        return $this->hasMany(ContentEntity::class);
    }
}

class ContentEntity extends Model {
    public function contentable() {
        return $this->morphTo();
    }
}

class Content extends Model {
    public function contentEntity() {
        return $this->morphOne(ContentEntity::class, 'contentable');
    }
}

class Video extends Model {
    public function contentEntity() {
        $this->morphOne(ContentEntity::class, 'contentable');
    }
}

This works but seems very unclean to me. I think it adds too much developer overhead to have to manage the ContentEntity parent.

Edit: Unless someone provides a better solution, I went with an EAV style solution using ContentEntitys.

like image 920
Sturm Avatar asked Jan 06 '16 21:01

Sturm


People also ask

Does an interface have a relationship?

It is used to achieve abstraction and multiple inheritance in Java. In other words, you can say that interfaces can have abstract methods and variables. It cannot have a method body. Java Interface also represents the IS-A relationship.

What kind of relationships of a system are implemented using interfaces?

The relationship is only the "contract" that the class is getting to implement the methods the interface is offering. That is how java can separate WHAT objects can do (Interface) and HOW the inherited class will do it.

What is the relationship between an interface and the class that implements the interface?

An Interface can be inherited by a class using the keyword 'implements' and it can be inherited by another interface using the keyword 'extends'. A class can contain constructors. An Interface cannot contain constructors. It cannot contain abstract methods.

How do you define a relationship in laravel?

To define a relationship, we need first to define the post() method in User model. In the post() method, we need to implement the hasOne() method that returns the result. Let's understand the one to one relationship through an example. First, we add the new column (user_id) in an existing table named as posts.


1 Answers

You could always extract the relationship to a trait for easier maintenance and extendability in the future:

Trait

trait Contentable
{
    public function contentEntity() {
        if(property_exists($this, 'contentable') && $contentable == 'many') {
            return $this->hasMany(ContentEntity::class);
        } else {
            return $this->morphOne(ContentEntity::class, 'contentable');
        }
    }

    // Future implementations
}

Then all you need to do is use the trait in various entities:

Models

class Content extends Model {
    use Contentable;
}

class Video extends Model {
    use Contentable;
}

class Article extends Model {
    use Contentable;

    protected $contentable = 'many';
}
like image 129
Dov Benyomin Sohacheski Avatar answered Oct 13 '22 23:10

Dov Benyomin Sohacheski