'Laravel Polymorphism for different content types (Multisite)
I started to develop a little Content Management System for two languages (de, en) that starts to grow bigger.
In that context, I have Posts and Pages (a bit like WordPress or actually just like WordPress). But I am also planning to add further content types like Reviews, Courses, Tutorials (Recipes) and maybe even E-Books that are purchasable.
All these objects would have in common that they are contentable, so they will be shown on the front end with their dedicated urls, like /posts/{slug} for posts, /{slug} for pages, /reviews/{slug} for reviews and so on.
On the backend, this means an auto save and revision system is offered for these content types.
So, this would leave us will the following options:
- Single Table Inheritance (we would need to live with many null values) - not supported officially by Laravel, but there is a package.
- Multi Table Inheritance (which is not supported in Laravel either)
- Polymorphism which is supported
- CMS solution (like craft CMS), which basically breaks up the logic in elements, entries, fields and so on, alternative approach would be drupal's node approach - out of scope I believe (I dont have 6-9 months time to write a CMS from the scratch)
- Have on Table per Model and try to use as much logic as possible between the models by using Traits (current status, I don't like it that much...).
After some googling, searching here on stackoverflow and looking at other projects, I am thinking of the following structure:
contents table:
id
site_id
title
... (some more columns that are shared among all models)
contentable_type
contentable_id
posts
id
pages
id
home
courses
id
name
featured
difficulty
free
So, these tables would be linked to the contents table through a belongsTo relationship, and the content model would define the morphable relationship.
class Content extends Eloquent {
public function contentable(){
return $this->morphTo();
}
}
class Post extends Eloquent (or Content) {
public function content(){
return $this->morphOne('Content', 'contentable');
}
}
Working with models would mean you would always have to load the content relationships.
Sorting & Ordering must be performed by joins.
And when creating, of course, we have to first create the content type model and then save and attribute it to a content model.
I never implemented a system with that kind of (sub) logic before, and it feels a bit odd to me to have a posts table with just an id (same would be true for other content types e.g. "abouts" in case they don't have extra columns), but I think it would be the "Laravel way" to solve this issue, right?
I believe STI wouldn't work for this case, and it is also a bit against Laravel's Eloquent pattern.
Has somebody already experiences with this approach? Am I on the right track here?
Note: I got inspired by the discussion here: How can I implement single table inheritance using Laravel's Eloquent?
Solution 1:[1]
In case anyone finds this question. I finally decided against this approach, basically because I believe it is not worth the efforts (and also most of the packages won’t work out of the box).
It is a much better approach to use Traits et cetera to reuse as much logic as possible and follow the Eloquent ORM approach.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Snake |