I am working on a blogging application in Laravel 8.
The ArticlesController controller I have this method to display the single article and its comments:
class ArticlesController extends FrontendController {
// More code
public function show($slug) {
// Single article
$article = Article::firstWhere('slug', $slug);
$old_article = Article::where('id', '<', $article->id)->orderBy('id', 'DESC')->first();
$new_article = Article::where('id', '>', $article->id)->orderBy('id', 'ASC')->first();
// Comments
$commentsQuery = Comment::where(['article_id' => $article->id, 'approved' => 1])->orderBy('id', 'desc');
$comments = $commentsQuery->paginate(10);
$comments_count = $commentsQuery->count();
return view('themes/' . $this->theme_directory . '/templates/single',
array_merge($this->data, [
'categories' => $this->article_categories,
'article' => $article,
'old_article' => $old_article,
'new_article' => $new_article,
'comments' => $comments,
'comments_count' => $comments_count,
'tagline' => $article->title,
])
);
}
}
In the view I have this for the comments list:
<div id="commentsList">
<ol class="commentlist {{ boolval($is_infinitescroll) ? 'infinite-scroll' : '' }}">
@foreach ($comments as $comment)
<li class="depth-1 comment">
<div class="comment__avatar">
<img class="avatar" src="{{ asset('images/avatars/' . $comment->user->avatar) }}" alt="" width="50" height="50">
</div>
<div class="comment__content">
<div class="comment__info">
<div class="comment__author">{{ $comment->user->first_name }} {{ $comment->user->last_name }}</div>
<div class="comment__meta">
<div class="comment__time">{{ date('jS M Y', strtotime($comment->created_at)) }}</div>
<div class="comment__reply">
<a class="comment-reply-link" href="#0">Reply</a>
</div>
</div>
</div>
<div class="comment__text">
<p>{{ $comment->body }}</p>
</div>
</div>
</li>
@endforeach
</ol>
<div class="ajax-load text-center is-hidden">
loading...
</div>
</div>
The routes related to the article(s):
// Article routes
Route::get('/', [ArticlesController::class, 'index'])->name('homepage');
Route::get('/category/{category_id}', [ArticlesController::class, 'category'])->name('category');
Route::get('/author/{user_id}', [ArticlesController::class, 'author'])->name('author');
Route::get('/show/{slug}', [ArticlesController::class, 'show'])->name('show');
The goal
I want to replace the comments pagination with an "infinite scroll".
For this purpose, I have:
/* Infinite comments */
function infiniteComments() {
var page = 1;
$(window).scroll(function() {
if ($(window).scrollTop() + $(window).height() >= $(document).height() - $('.s-footer').height()) {
page++;
loadMoreData(page);
}
});
}
function loadMoreData(page){
var base_url = window.location.href.split('?')[0];
$.ajax({
url: `${base_url}?page=${page}`,
type: "get",
beforeSend: function() {
$('.ajax-load').show();
}
})
.done(function(data) {
if (data.html == "") {
$('.ajax-load').hide();
return;
}
$('.ajax-load').hide();
$(".infinite-scroll").append(data.html);
})
.fail(function(jqXHR, ajaxOptions, thrownError) {
console.log('The server is not responding...');
});
}
$(document).ready(function(){
infiniteComments();
});
The problem
While accessing https://larablog.com/show/deserunt-qui-exercitationem?page=2 shows the comments on page 2 correctly, the Chrome console shows these 500 (Internal Server Error) errors:
https://larablog.com/show/deserunt-qui-exercitationem?page=65 500 (Internal Server Error)
The server is not responding...
https://larablog.com/show/deserunt-qui-exercitationem?page=76 500 (Internal Server Error)
The server is not responding...
The error can be tracked back to this error message in ArticlesController, at line 70 - $article = Article::firstWhere('slug', $slug):
Trying to get property 'id' of non-object.
This is strange because $article = Article::firstWhere('slug', $slug) works fine without Ajax.
Questions
- What causes this bug?
- What is the easiest fix?
console.log(thrownError)throwsInternal Server Error.ArticlesController:Trying to get property 'id' of non-object, but the log does not say on what line.