On my site, users can post "statuses", and other users can reply/comment on those statuses. On the front page of my site, for example, I have the most liked statuses of the past 3 days displayed.
In my HomeController.php:
$statuses = Status::where('is_image', 1)
->where('is_mature', 0)
->where('created_at', '>=', Carbon::now()->subHours(168))
->orderBy('like_count', 'desc')
->take(6)
->get();
Statuses can also have replies. Replies use the same table as the status table. Replies are pretty much just statuses with a "parent" status, and regular statuses are just statuses without a "parent".
From the model status.php:
public function scopeNotReply($query) {
return $query->whereNull('parent_id');
}
public function replies() {
return $this->hasMany('CommendMe\Models\Status', 'parent_id');
}
So back to my home page, here's how the statuses are loaded on the home page:
home.blade.php:
@if ($statuses->count())
@foreach ($statuses as $status)
<div class="post-container">
...
blah blah blah
...
@foreach ($status->replies->reverse()->slice(0, 3) as $reply)
<div class="status-reply-content">
...
blah blah blah
...
</div>
@endforeach
@if (count($status->replies) > 3)
<a href="#">
View More Comments ({{ count($status->replies) }})
</a>
@endif
</div>
@endforeach
@endif
What I want is for the "View More Comments" button to load another set of 3 comments.
This would be simple if these were being paginated. In fact, elsewhere on my site I load more images through ajax. Like so:
if($request->ajax()) {
return [
'images' => view('browse.partials.fullview_partial')->with('images', $images->appends(request()->only('query')))->render(),
'next_page' => $images->nextPageUrl()
];
}
however this relies on loading in the next set of pagination through ajax. Whereas the $status->replies
relationship is not being paginated.
So how could I load more replies in this scenario?
Edit:
Even an alternate solution would help.
Do you need to load the first page of replies server-side? I guess since you are willing to load subsequent pages with AJAX you could just handle all client-side and just have an AJAX endpoint that provides the data.
Just make ajax calls to your endpoint passing the status id and page number.
// AjaxController
public function replies()
{
$status = Status::findOrFail(request('id'));
return $status->replies()->paginate(3);
}
(The page number will be resolved automatically.)
This will return a JSON representation of the paginator, which has the urls for previous and next pages, and the data for the current page. Then just render the data client-side.
What I ended up doing was simply creating a new function in my controller for the request itself, and then sending the ID of the status along with it, along with a skip count (that increases based on how many replies are already loaded) to skip the loaded replies.
public function getReplies($statusID, $skip, Request $request) {
$status = Status::findOrFail($statusID);
$replies = $status->replies()->orderBy('created_at', 'desc')->skip($skip)->take(10)->get();
if($request->ajax()) {
return [
'replies' => view('templates.partials.replies')->with('replies', $replies)->render(),
];
}
}
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