I don't think you need to define so many relationships on one entity. Let me know if I am correct to assume the following:
Also, I would like to know which db you are intending to use, and if you follow the repository pattern.
When I fully understand the problem, I will be happy to help make the models, repositories (if used), and the queries.
What you need is polymorphic relationship. I suggest something flexible, so you don't need to make changes to other models, only add relation definition there. Check this:
//Vote model
// relation
public function voteable()
{
return $this->morphTo();
}
// setup some static methods on this model to easily fetch what you need, for example:
public static function up(Model $voteable)
{
return (new static)->cast($voteable, 1);
}
public static function own(Model $voteable)
{
return (new static)->cast($voteable, -1);
}
protected function cast(Model $voteable, $value = 1)
{
if ( ! $voteable->exists) return false; // false as an example, throw meaningful exception here if you like
$vote = new static;
$vote->value = $value;
return $vote->voteable()->associate($voteable)->save();
}
Now on every model you'd like to be voteable you need just the relation:
public function votes()
{
return $this->morphMany('Vote', 'voteable');
}
With this setup you can do this:
$post = Post::find(15);
Vote::up($post); // true
Vote::down($post); // true
// on non-existing models
$comment = new Comment;
Vote::up($comment); // false
$comment->save();
Vote::up($comment); // true
// of course there are other useful methods to implement, for example
Vote::sum($post); // votes sum for given post
Vote::count($post); // votes count
Vote::countUps($post); // up votes count
Last thing would be accessor on the Vote
model so you can restrict what values can be set:
public function setValueAttribute($value)
{
$this->attributes['value'] = ($value == -1) ? -1 : 1;
}
And by the way, this very example I gave you, doesn't really require any changes at all on the voteable models, even the relationship there is not needed.
Thanks for the replies jarek and rowdy.
I don't think I need a polymorphic relationship. I'm not trying to attach a rating system to different types of models since I plan for only posts to have a rating. Your code did give me a better understanding of when a polymorphic relationship can be used and why though so thanks! I think your example could be really useful in an upcoming project.
Let me try to explain a little more clearly what I'm trying to accomplish and answer some of rowdy's questions.
My rating table has the columns: post_id, user_id, score.
My database is MySQL and I'm using Eloquent for queries.
#Page interactions:
#What I would like for it to look like:
Now that I think about it, the rating system I'm wanting is similar to the way that Amazon displays reviews. However, the user can have multiple comments instead of just 1 comment/review.
Let me know what you think of this and we can move ahead setting up the models:
Idea A:
User:
Post:
Comment:
pivot table post_user:
Naturally, there will be more models and relationships in your ecosystem. The pivot table allows us to join disparate types of relationships and store information on it. This will allow more flexibility than....
Idea B:
User:
Post:
UserRating:
Comment:
Sorry if I bump this after so long.
I really like jarektkaczyk's answer but I don't understand how he think the database migrations should work here. Any advice?
Are you suggesting a "votes" table with foreign keys for each resource or changing the single resource's tables to include a votes_up and a votes_down field?
Sign in to participate in this thread!
The Laravel portal for problem solving, knowledge sharing and community building.
The community