Create AJAX Pagination with PHP and MySQL

AJAX pagination with a validated page number

AJAX pagination can request one page of records as JSON and update the table without reloading the full document. The browser sends a page number, while PHP validates it, calculates the offset, and returns both rows and navigation metadata.

Demo of AJAX paging script

1. Request a page with Fetch

Keep the client contract small: send only the requested page number. URLSearchParams handles URL encoding, and the response is parsed as JSON.

async function loadPage(page) {
  const params = new URLSearchParams({ page: String(page) });
  const response = await fetch(`php_paging-ajaxck.php?${params}`);
  const payload = await response.json();

  if (!response.ok) {
    throw new Error(payload.error || 'Unable to load records');
  }

  renderRows(payload.data);
  nextButton.disabled = !payload.hasNext;
  previousButton.disabled = !payload.hasPrevious;
}

2. Validate the page on the server

Client-side values cannot be trusted. Accept only integers greater than or equal to 1. Invalid page values should return an HTTP 400 response instead of being used in SQL.

<?php
$pageRaw = $_GET['page'] ?? '1';

if (filter_var(
    $pageRaw,
    FILTER_VALIDATE_INT,
    ['options' => ['min_range' => 1]]
) === false) {
    http_response_code(400);
    echo json_encode(['error' => 'Invalid page number']);
    exit;
}

$page = (int) $pageRaw;
?>

3. Count rows and calculate the offset

Use COUNT(*) to obtain the total number of records. Avoid relying on rowCount() for SELECT queries because its behavior is driver-dependent.

$limit = 10;
$totalRecords = (int) $dbo->query('SELECT COUNT(*) FROM student')->fetchColumn();
$totalPages = max(1, (int) ceil($totalRecords / $limit));
$page = min($page, $totalPages);
$offset = ($page - 1) * $limit;

4. Bind LIMIT and OFFSET as integers

An explicit ORDER BY keeps paging stable, and integer binding keeps request-derived values out of the SQL string.

$stmt = $dbo->prepare(
    'SELECT id, name, class AS myclass, mark FROM student ORDER BY id LIMIT :limit OFFSET :offset'
);
$stmt->bindValue(':limit', $limit, PDO::PARAM_INT);
$stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

5. Return rows with paging metadata

echo json_encode([
  'data' => $rows,
  'page' => $page,
  'totalRecords' => $totalRecords,
  'totalPages' => $totalPages,
  'hasPrevious' => $page > 1,
  'hasNext' => $page < $totalPages,
]);

6. Render returned values as text

Database values should be placed into cells with textContent rather than concatenated into an HTML string. This keeps record data from being interpreted as markup.

rows.forEach((record) => {
  const td = document.createElement('td');
  td.textContent = String(record.name ?? '');
});
Key point: the browser controls which page it asks for, but the server controls validation, bounds, SQL, and the metadata that decides whether Previous or Next should be enabled.
First page with the Previous button unavailable Last page with the Next button unavailable
Ajax based PHP script with record DELETE option
Ajax Json XML


Subscribe to our YouTube Channel here



plus2net.com







arifxxx

13-06-2014

this is one of the best tutorial what i've know
subbu

26-02-2017

how to implement or add one more button that retrieve all records at once?

can you provide the code for that?

thanks.
smo1234

28-02-2017

Your query reads like this
$query=" SELECT * FROM student limit $eu, $limit ";
If you remove limit part and make it like this.
$query=" SELECT * FROM student ";
You can display all the records. With the button you can pass a variable like this
<a href=page_name.php?display_status=dispaly_all>Show all</a>
Collect display_status like this at the top of the page.
$display_all=$_GET['display_all'];
if($dispaly_all=='display_all'){
$q='SELECT * FROM student';
}else{
$q='SELECT * FROM student limit $eu,$limit';
}

Php Developer

01-06-2018

Nice work! This is massively helpful to me. It just made my work easier. It saved lot of time.

Thanks.




PHP video Tutorials
✖
We use cookies to improve your browsing experience. . Learn more
HTML MySQL PHP JavaScript ASP Photoshop Articles Contact us
© 2000-2026 plus2net.com All rights reserved worldwide Privacy Policy Disclaimer