Currently I have a model class named Post
.
class Post extends Eloquent {
protected $table = 'posts';
protected $fillable = array('user_id', 'title', 'description', 'views');
/*
* Relationships
*/
public function user()
{
return $this->belongsTo('User');
}
public function tags()
{
return $this->belongsToMany('Tag', 'post_tags');
}
public function reactions()
{
return $this->hasMany('Reaction');
}
public function votes()
{
return $this->hasMany('PostVote');
}
//Scopes and functions...
}
I would like to divide posts into two different types; articles
and questions
. I thought the best way to do this is by inheritance, so Article
and Question
would extend Post
. What is the best way to do this and where to start?
from Laravel 5.2,
Global Scope
is available:where type = 'article'
is added to all query ofArticle
just likeSoftDeletes
.Actually laravel provide
SoftDeletes
trait using this feature.Before I dig into multi table inheritance I want to lose a few words about single table inheritance. Single table inheritance is the more easy way when it comes to inheritance with db models.
You have multiple models bound to the same table and a
type
column to distinguish between the different model classes. However the reason you normally want to implement inheritance is because the models have shared properties but also some that are unique to the model.When using single table inheritance your table looks similar to that at some point:
You end up having a lot of NULL values because there are columns not needed for a certain type of model. And with a lot of records this can influence the size of database.
However for some cases it might still be the best solution. Here's a well written Tutorial that shows how to implement it in Laravel in a pretty elegant way.
Multi Table Inheritance
Now lets look at multi table inheritance. With this method you split your single table into multiple ones (well I guess the name gave that kind of away already ;)) We are going to use a technique called Polymorphism
Our schema from the example above would look like this:
A lot cleaner if you ask me...
The interesting columns here are
postable_id
andpostable_type
. The type tells us on which table we will find our "rest" of the model and the id specifies the primary key of the record that belongs to it. Note that the column names could be whatever you want, but it is convention to call it "-able".Lets take a look at the Eloquent models now.
Post
Question / Article / every other postable type
Note that you actually don't have to extend from
Post
but you can if you maybe have methods that you want to use too. Anyways, the polymorphic relationship will work with or without it.Ok that's the basic setup. Here's how you can use your new models:
Retrieve all posts
Retrieve all questions
Get question columns from a post
Get post properties from question
Check which type a post is
Create new question
Now bear with me, creating a model is a bit more complicated. If you have to do it at multiple places in your application I suggest you write a reusable function for it.
So as you can see, a clean database comes with it's price. It will be a bit more complex to handle your model. However you can put all these extra logic (e.g. that's required to create a model) into a function in your model class and don't worry about it too much.
Also, there's a nice Tutorial for multi table inheritance with laravel too. Maybe it helps ;)