My website has comments. These comments can have "votes", upvotes and downvotes.
I have a Comment Model and a CommentVote model.
In my comment model I have a functions that returns the votes:
public function votes() {
return $this->hasMany('App\CommentVote', 'comment_id');
}
public function upvotes() {
return $this->hasMany('App\CommentVote', 'comment_id')->where('vote', 1);
}
public function downvotes() {
return $this->hasMany('App\CommentVote', 'comment_id')->where('vote', -1);
}
Notice that upvotes are stored in the database in a tinyInt as 1 and downvotes are stored as -1
In my CommentVote model I have the belongsTo relationship:
public function comment() {
return $this->belongsTo('App\Comment');
}
Now I want to have a function that calculates the total "score" of the comment. Total upvotes minus total downvotes.
I try to make a function that counts all the upvotes - all the downvotes.
public function score() {
return $this->upvotes()->count() - $this->downvotes()->count();
}
This returns the error:
App\Comment::score must return a relationship instance.
In fact using the count() anywhere will return this error, despite it working fine in my other Models.
Doing something simple like:
public function voteCount() {
return $this->hasMany('App\CommentVote', 'comment_id')->count();
or even
return $this->votes()->count();
}
will return the error:
App\Comment::voteCount must return a relationship instance.
Why is this happening?
EDIT:
Here is the controller, as per requests in the comments:
public function getSubmission($subchan, $id, $URLtitle) {
$submission = Submission::where('id', $id)->first();
$comments = Comment::where('submission_id', $submission->id)->where('parent_id', NULL)->orderBy('created_at', 'desc')->get();
$comments = $comments->sortByDesc(function($comment){
return count($comment['upvotes']) - count($comment['downvotes']);
});
if (!$submission) {
return redirect()->route('home')->with('error', 'Submission not found.' );
}
return view('submissions.submission')
->with('submission', $submission)
->with('navSubchan', $submission->getSubchan->name)
->with('submissionPage', 1)
->with('comments', $comments)
;
}
I suspect you're doing $model->score, which is going to look for a function called score(), but in a specific manner that expects that function to return a HasMany, HasOne, BelongsTo etc. style relationship object.
Consider an accessor function instead.
public function getScoreAttribute() {
return $this->upvotes()->count() - $this->downvotes()->count();
}
allows you to do $model->score successfully.
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