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 ContentEntity
s.
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.
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.
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.
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.
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';
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With