Hi guys ,
I'm going to share with you a trick that have saved me lot of work and avoid me to use more table with my DB .
Lets start with the problem that I was trying to solve using Eloquent Polymorphic Relations. Lets say we have a topic which could have many posts, and users will be able to leave comments about the topic itself and also about the posts within this topic. I think this is a good situation to go with single table that store comments for both tables 'topics' and 'posts' , but my issue was how I can determine which user made this comment and where( commented on topic or in post). so to solve this issue here is my solution:
First let me share with you the DB schema for this example :
users
id - integer
username- string
email -string
password -string
topics
id - integer
title- string
posts
id - integer
body- text
Since I want to know which user made the comment I have to set relationship between users table and comments table like so:
comments
id - integer
body- text
user_id-integer
commentable_id - integer
comment_type - string
Now you have an idea about DB structure, lets create our models for thus guys:
User Model
<?php
class User extends Eloquent{
/**
* @var string Table
*/
protected $table = 'users';
}
Comment Model
<?php
class Comment extends Eloquent{
/**
* @var string Table
*/
protected $table = 'comments';
public function commentable()
{
return $this->morphTo();
}
public function user()
{
return $this->belongsTo('User');
}
}
Topic Model
<?php
class Topic extends Eloquent{
/**
* @var string Table
*/
protected $table = 'topics';
public function comments()
{
return $this->morphMany('Comment', 'commentable');
}
}
Post Model
<?php
class Post extends Eloquent{
/**
* @var string Table
*/
protected $table = 'posts';
public function comments()
{
return $this->morphMany('Comment', 'commentable');
}
}
Now lets create our first comment for the topic with id 1:
$topic = Topic::find(1);
$topic->comments()->create(['body' => 'blah for topic', 'user_id' => Auth::id()]);
Now you should have your comment for the topic stored within the comments table , something that you should be aware of ,is that commentable_id field will have the id of the topic which is 1 and the commentable_type will store the model name which is Topic.
lets do the same thing for the post with Id of 2 :
$post= Post::find(2);
$post->comments()->create(['body' => 'blah for post', 'user_id' => Auth::id()]);
Now commentable_id will have the id of the post which is 2 and the commentable_type will store the model name which is Post.
Since now everything in place I can get the Topic comments and determine which user have left this comment like so:
$topic = Topic::find(1);
foreach($topic->comments as $comment)
{
echo "Comment By: {$comment->user->username} <br />";
echo $comment->body;
}
We can do the same thing for posts :
$post = Post::find(2);
foreach($post->comments as $comment)
{
echo "Comment By: {$comment->user->username} <br />";
echo $comment->body;
}