Phân trang là một chức năng không thể thiếu của một trang web có dữ liệu lớn. Ví dụ trang web của mình là một trang web với nhiều bài viết, không thể nào show tất cả bài viết ra trong cùng một trang được điều đó ảnh hưởng đến tốc độ load trang và người dùng cũng không mong muốn scroll chuột xuống quá nhiều để tìm kiếm bài viết. Trong bài viết này mình sẽ hướng dẫn các bạn làm chức năng phân trang với Ajax, PHP và MYSQL.
1. Chuẩn bị dữ liệu đầu vào
Tất nhiên chúng ta phải có dữ liệu để có thể thực hiện phân trang đúng không nào. Các bạn tạo một cơ sở dữ liệu mới và chạy query bên dưới để thêm dữ liệu vào nhé:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
-- -- Table structure for table `posts` -- DROP TABLE IF EXISTS `posts`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `posts` ( `post_id` int(11) NOT NULL AUTO_INCREMENT, `post_name` varchar(255) DEFAULT NULL, PRIMARY KEY (`post_id`) ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; -- -- Dumping data for table `posts` -- LOCK TABLES `posts` WRITE; /*!40000 ALTER TABLE `posts` DISABLE KEYS */; INSERT INTO `posts` VALUES (1,'vi-magento'),(2,'Ajax là gì'),(3,'Magento 2 là gì'),(4,'PHP là gì'),(5,'Javascript'),(6,'Pecl'),(7,'C++'),(8,'Java'),(9,'Wordpress'),(10,'Shopify'),(11,'HTML'); /*!40000 ALTER TABLE `posts` ENABLE KEYS */; UNLOCK TABLES; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; -- Dump completed on 2021-06-26 22:13:18 |
2. Viết các hàm để lấy dữ liệu từ database
Để làm được chức năng phân trang thì chúng ta cần lấy ra được tổng số bài viết để có thể tính được tổng số trang. Và từ đó sẽ lấy ra các bài viết của mỗi trang.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
<?php global $conn; // Hàm kết nối database function connect(){ global $conn; $conn = mysqli_connect('localhost', 'vimagento', '123456', 'ajax') or die ('{error:"bad_request"}'); } // Hàm đóng kết nối function disconnect(){ global $conn; if ($conn){ mysqli_close($conn); } } // Lấy tổng số bài viết function count_posts() { global $conn; $query = mysqli_query($conn, 'select count(*) as total from posts'); if ($query){ $row = mysqli_fetch_assoc($query); return $row['total']; } return 0; } // Lấy bài viết theo số trang function get_all_post($limit, $start) { global $conn; $sql = "select * from posts limit {$limit}, {$start}"; $query = mysqli_query($conn, $sql); $result = array(); if ($query) { while ($row = mysqli_fetch_assoc($query)) { $result[] = $row; } } return $result; } |
3. Giao diện chính của phân trang với ajax
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
<?php require_once "database.php"; connect(); // Kết nối đến database; // Mặc định sẽ là trang 1. $current_page = isset($_GET['page']) ? $_GET['page'] : 1; $postTotal = count_posts();// Lấy tổng số bài viết. $postOnePage = 3; // Số bài viết hiển thị trong 1 trang. // Khi đã có tổng số bài viết và số bài viết trong một trang ta có thể tính ra được tổng số trang $pageTotal = ceil($postTotal / $postOnePage); $limit = ($current_page - 1) * $postOnePage; $data = get_all_post($limit, $postOnePage); // Kiểm tra nếu là ajax request thì trả kết quả if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') { $output = ''; $output .= '<div class="panel-body"> <table class="table table-striped table-bordered table-list"> <thead> <tr> <th class="hidden-xs">ID</th> <th>Name</th> </tr> </thead> <tbody id="content">'; foreach ($data as $item) { $output .= '<tr>'; $output .= '<td>' . $item['post_id'] . '</td>'; $output .= '<td>' . $item['post_name'] . '</td>'; $output .= '</tr>'; } $output .= '</tbody> </table> </div>'; // Phân trang $output .= '<div class="panel-footer"> <div class="row"> <div class="col col-xs-8"> <ul class="pagination hidden-xs pull-right">'; if ($current_page > 1) { $output .= '<li><a href="index.php?page=' . ($current_page - 1) . '">«</a></li>'; } for ($i = 1; $i <= $pageTotal; $i++) { $class = ($current_page == $i) ? 'disabled' : ''; $output .= '<li class="' . $class . '">'; $output .= '<a href="index.php?page=' . $i . '">' . $i . '</a>'; $output .= '</li>'; } if ($current_page < $pageTotal) { $output .= '<li><a href ="index.php?page='.($current_page + 1).'">»</a></li>'; } $output .= '</ul> </div> </div> </div>'; die($output); } disconnect(); // Ngắt kết nối database. ?> <!DOCTYPE html> <html> <head> <title></title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css"> <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script> <script src="//code.jquery.com/jquery-1.11.1.min.js"></script> <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.4.0/css/font-awesome.min.css" rel='stylesheet' type='text/css'> </head> <body> <div class="container"> <div class="row"> <div class="col-md-10 col-md-offset-1"> <h1>Phân trang với Ajax, PHP và MYSQL</h1> <div class="panel panel-default panel-table"> <div class="panel-body"> <table class="table table-striped table-bordered table-list"> <thead> <tr> <th class="hidden-xs">ID</th> <th>Name</th> </tr> </thead> <tbody id="content"> <?php foreach ($data as $post): ?> <tr> <td class="hidden-xs"><?= $post['post_id']; ?></td> <td><?= $post['post_name']; ?></td> </tr> <?php endforeach; ?> </tbody> </table> </div> <div class="panel-footer"> <div class="row"> <div class="col col-xs-8"> <ul class="pagination hidden-xs pull-right"> <?php if ($current_page > 1): ?> <li><a href="index.php?page=<?= $current_page - 1; ?>">«</a></li> <?php endif; ?> <?php for ($i = 1; $i <= $pageTotal; $i++): ?> <li class="<?= ($current_page == $i) ? 'disabled' : ''; ?>"> <a href="index.php?page=<?= $i; ?>"><?= $i; ?></a> </li> <?php endfor; ?> <?php if ($current_page < $pageTotal): ?> <li><a href="index.php?page=<?= $current_page + 1; ?>">»</a></li> <?php endif; ?> </ul> </div> </div> </div> </div> </div> </div> </div> <script language="JavaScript"> $(<strong><em>document</em></strong>).ready(function () { $('body').on('click', '.pagination li a', function (e) { e.preventDefault();// Không load lại trang khi click phân trang. let url = $(this).attr('href'); $.ajax({ url: url, method: 'GET', dataType: 'text', success: function (response) { $('.panel-table').html(response); // Thay đổi URL trên website <strong><em>window</em></strong>.history.pushState({path:url},'',url); } }); }); }); </script> </body> </html> |

Giải thích về chức năng Phân trang với Ajax ở trên
1 2 3 4 5 |
if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') { $output = ''; //....// die($output); } |
Vì mình đã gửi 1 yêu cầu Ajax đến trang hiện tại luôn và trong hàm Ajax mình có để dataType là text. Nên khi trả dữ liệu về cho Ajax mình phải kiểm tra đó có phải là yêu cầu Ajax không và sử dụng die($output)
. Nếu không nó sẽ trả về cả đoạn html bên dưới nữa.
1 |
<strong><em>window</em></strong>.history.pushState({path:url},'',url); |
Đoạn này được sử dụng để thay đổi url thành url hiện tại. Để khi bạn load lại trang thì vẫn ra kết quả.
Trong bài viết này mình đã hướng dẫn các bạn làm chức năng phân trang với Ajax, PHP và Mysql. Hy vọng bài viết hữu ích với các bạn. Nếu có bất cứ thắc mắc gì về bài viết, đừng ngần ngại để lại bình luận bên dưới nhé.
Source code: https://github.com/vimagento/pagination-ajax