I have made a blogging application in Laravel 8.
The articles support comments and the comments need to be approved by an admin before being published.
In the CommentController controller, I have:
class CommentController extends Controller
{
public function index(Request $request)
{
// Total number of comments
$comments_count = Comment::count();
// Total number of unapproved comments
$unapproved_comments_count = Comment::where('approved', 0)->count();
// Comments per page
$per_page = 10;
// Comments filters
$filters = $filter = [
(object)[
'value' => 'all',
'label' => 'All comments'
],
(object)[
'value' => 0,
'label' => 'Unapproved'
],
(object)[
'value' => 1,
'label' => 'Approved'
]
];
// Comments (with filter)
$filter = $request->input('filter');
$comments = Comment::orderBy('id', 'desc')
->when($filter !== 'all', function ($query) use ($filter) {
return $query->where('approved', $filter);
}, function ($query) {
return $query->where('approved', 1)->orWhere('approved', 0);
})
->paginate($per_page)->onEachSide(1);
return view(
'dashboard/article-comments',
[
'per_page' => $per_page,
'current_page' => $comments->currentPage(),
'comments' => $comments,
'comments_count' => $comments_count,
'unapproved_comments_count' => $unapproved_comments_count,
'filters' => $filters
]
);
}
public function approve($id)
{
Comment::find($id)->update(['approved' => 1]);
return redirect()->back()->with('success', 'The comment was approved');
}
public function unapprove($id)
{
Comment::find($id)->update(['approved' => 0]);
return redirect()->back()->with('success', 'The comment was unapproved');
}
}
Inside the comments view, I have the following select-box that is supposed to help display the approved, unapproved and all comments.
<form class="d-flex align-items-center" method="get" action="{{ route('dashboard.comments')}}">
@csrf
<label for="commentsFilter" class="form-label mb-0 me-1">Status</label>
<select class="form-select" id="commentsFilter" name="filter" onchange="this.form.submit()">
@foreach ($filters as $filter)
<option value="{{ $filter->value }}">{{ $filter->label }}</option>
@endforeach
</select>
</form>
The following piece of code in the controller shows approved or unapproved comments, but fails when I want to display all the comments.
$filter = $request->input('filter');
$comments = Comment::orderBy('id', 'desc')
->when($filter !== 'all', function ($query) use ($filter) {
return $query->where('approved', $filter);
})
->paginate($per_page)->onEachSide(1);
Nothing happens when I pick "All comments". I am left with the current selection (either the approved or the unapproved comments).
NOTE
Using return $query->where('approved', 1)
returns all approved comments, and return $query->where('approved', 0)
returns all unapproved ones, as expected.
In your current code, the issue lies in the condition when($filter !== 'all') inside the query builder. When the selected filter is "All comments", the condition evaluates to true, and the where clause is applied to filter the comments by approval status. However, since you want to display all comments in this case, you need to modify the condition to include the "All comments" filter as well.
Here's an updated version of the code that should address the issue:
$comments = Comment::orderBy('id', 'desc')
->when($filter !== 'all', function ($query) use ($filter) {
return $query->where('approved', $filter);
}, function ($query) {
// Add a fallback condition to include all comments when $filter === 'all'
})
->paginate($per_page)->onEachSide(1);
This modification adds a fallback function to the when method, which will be executed when the condition evaluates to false. In this case, it doesn't apply any additional filtering, effectively including all comments in the result.
By making this change, the comments will be correctly filtered when "Unapproved" or "Approved" is selected, and all comments will be shown when "All comments" is selected.
Additionally, make sure that the value attribute of the "All comments" option in the select box is set to "all" so that it matches the value used in the condition.
<option value="all">All comments</option>
With these adjustments, the issue should be resolved, and you should be able to display the desired comments based on the selected filter option.
Or you can reference these links to get more information: https://laravel.com/docs/8.x/controllers
https://stackoverflow.com/questions/51223265/how-to-show-comments-and-replycomments-in-laravel
@alanrodgers I did this:
$comments = Comment::orderBy('id', 'desc')
->when($filter !== 'all', function ($query) use ($filter) {
return $query->where('approved', $filter);
}, function ($query) {
// Get approved and approved comments
return $query->where('approved', 1)->orWhere('approved', 0);
})
->paginate($per_page)->onEachSide(1);
It does not work. What would be a working alternative?
Sign in to participate in this thread!
The Laravel portal for problem solving, knowledge sharing and community building.
The community