Support the ongoing development of Laravel.io →
Blade Laravel Alpine.js
Last updated by @ajax30 2 weeks ago.
1

Root Cause: Your current get_comments_ajax() method ends with:

echo json_encode([ 'html' => $content, 'page' => $page_number, 'more_comments_to_display' => $more_comments_to_display, 'article_id' => $article_id ]); exit();

This “works”, but only if absolutely no output (spaces, BOM, debug lines, notices) happens before or after the method. Laravel, however, buffers responses, and using echo/exit() bypasses its response system — that’s dangerous.

So what’s happening is:

Laravel may prepend/append output buffering characters,

or a stray newline / space / UTF-8 BOM breaks JSON,

so your JS sees: SyntaxError: Unexpected end of JSON input

Correct Laravel Way Replace your last part with a proper JSON response using Laravel’s response()->json().

Fixed get_comments_ajax(): `public function get_comments_ajax(Request $request) { if (!$request->ajax()) { abort(400, 'Invalid request'); }

$article_id  = $request->post('article_id');
$page_number = $request->post('page');
$offset      = $this->comments_per_page * $page_number;
$more_comments_to_display = true;

$data['comments'] = $this->get_commentQuery($article_id, $this->comments_per_page, $offset)
    ->whereNull('parent_id')
    ->with(['user', 'replies.user'])
    ->get();

$content = '';
if ($data['comments']->count()) {
    $content .= view(
        'themes/' . $this->theme_directory . '/partials/comments-list',
        array_merge($data, [
            'is_infinitescroll' => $this->is_infinitescroll,
            'theme_directory'   => $this->theme_directory,
            'article_id'        => $article_id
        ])
    )->render();
} else {
    $more_comments_to_display = false;
}

return response()->json([
    'html' => $content,
    'page' => $page_number,
    'more_comments_to_display' => $more_comments_to_display,
    'article_id' => $article_id
]);

}`

Key changes:

->render() on the Blade view ensures you get a string (not a View object).

response()->json() sends correct headers (Content-Type: application/json).

Removed echo and exit() (not recommended in Laravel).

Handles invalid requests gracefully.

Why Your JS Failed When fetch() tried to run: const text = await response.text(); data = JSON.parse(text); the variable text was empty or broken because Laravel’s output was not pure JSON. Hence → Unexpected end of JSON input.

Optional improvement (JS side) Since the response is guaranteed JSON, simplify your code:

const response = await fetch(${window.location.origin}/load_comments`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken }, body: JSON.stringify({ article_id: articleId, page }) });

const data = await response.json();

if (data.html) { const lastCommentCard = getLastCommentCard(); lastCommentCard.insertAdjacentHTML('afterend', data.html); currentPage++; moreComments = data.more_comments_to_display; } else { moreComments = false; }` Now your JSON parsing is clean, and you’ll never hit that error again.

0

Sign in to participate in this thread!

Native PHP

Your banner here too?

Razvan ajax30 Joined 2 Oct 2021

Moderators

We'd like to thank these amazing companies for supporting us

Your logo here?

Laravel.io

The Laravel portal for problem solving, knowledge sharing and community building.

© 2025 Laravel.io - All rights reserved.