jQuery Ajax pagination load more với PHP và MYSQL - Học Ajax - PHP Ajax - jQuery Ajax
Một số website có chức năng khi chúng ta kéo xuống dưới sẽ tự động hiển thị thêm tin, cái này ta gọi là ajax scrolling pagination. Còn trường hợp ở cuối danh sách có một button load more thì đấy ta gọi là Ajax pagination load more. Trong bài này chúng ta sẽ tìm hiểu thủ thuật load more này ...
Một số website có chức năng khi chúng ta kéo xuống dưới sẽ tự động hiển thị thêm tin, cái này ta gọi là ajax scrolling pagination. Còn trường hợp ở cuối danh sách có một button load more thì đấy ta gọi là Ajax pagination load more. Trong bài này chúng ta sẽ tìm hiểu thủ thuật load more này nhé, còn thủ thuật kia đã có bài trình bày rồi.
1. Ý tưởng kỹ thuật jQuery ajax pagination load more
Các bạn thấy khi chúng ta load lần đầu thì sẽ lấy trang thứ nhất, khi click load more thì sẽ load trang tiếp theo và thêm vào phần dưới cùng của danh sách, như vậy chúng ta sẽ dùng hàm append
trong jQuery và kết hợp PHP để trả về danh sách tin tương ứng từng trang. Tuy nhiên có một câu hỏi đặt ra là ở Server có cần tính tổng số trang để tìm limit và start hay không? Câu trả lời là không cần nhé, chúng ta sẽ dùng một mẹo nhỏ là sẽ select dư 1 record (nghĩa là limit = limit + 1), sau đó đếm tổng số record trả về nếu:
- Nếu tổng số record bằng limit + 1 thì nghĩa là còn tin cho trang kế, lúc này ta không cần ẩn button load more, khi lặp sẽ không lặp record cuối cùng vì đây là record dùng để check dữ liệu còn hay không
- Nếu bé hơn limit +1 thì nghĩa là trang kế ko còn tin nào, lúc này ta ẩn button load more
Như vậy là chúng ta không cần phải sử dụng thuật toán phân trang để xử lý.
2. Các bước thực hiện ajax pagination load more
Chúng ta sẽ làm một ví dụ đó là tạo một trang hiển thị danh sách khách hàng.
Tạo database để phân trang khi click vào load more
Tạo database:
CREATE TABLE IF NOT EXISTS `tb_customer` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `name` VARCHAR(255) COLLATE utf8_unicode_ci DEFAULT NULL, `website` VARCHAR(255) COLLATE utf8_unicode_ci DEFAULT NULL, UNIQUE KEY `id` (`id`) ) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=11 ;
Thêm một vài record:
INSERT INTO `tb_customer` (`id`, `name`, `website`) VALUES (1, 'Nguyễn Văn Cường', 'Zaidap.com.net'), (2, 'Trương Phúc Hoài Minh', 'Zaidap.com.net'), (3, 'Đặng Văn Chương', 'Zaidap.com.net'), (4, 'Trương Tấn Thành', 'Zaidap.com.net'), (5, 'Lâm văn Lang', 'demo.com'), (6, 'Nguyễn Văn Kiệt', 'ajax.com'), (7, 'Nguyễn Thị Nở', 'thimau.com'), (8, 'Đặng Thị Thoa', 'scrolling.com'), (9, 'Trương Văn Kiệt', 'ajaxscrolling.com'), (10, 'Đặng Thị Tâm', 'nono.com');
Tạo trang hiển thị danh sách khách hàng list.php
<!DOCTYPE html> <html> <head> <title></title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <script language="javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script> <script language="javascript" src="ajax.js" ></script> <style type="text/css"> .button{ display: inline-block; background: blue; padding: 5px 10px; color:#FFF; margin: 20px; } </style> </head> <body> <div id="content"> <?php require('data.php'); ?> </div> <a href="#" class="button" id="load_more">LOAD MORE</a> </body> </html>
Trong file này mình có thêm thư viện jquery, một file ajax.js
, một button load more và cuối cùng là có require file data.php
(file này sẽ tạo ở phần dưới)
File data.php kết nối xử lý database phân trang load more
File này có nội dung như sau:
<?php // Thiết lập kết quả trả về là html và charset là utf8 để khỏi lỗi font header('Content-Type: text/html; charset=utf-8'); // Kết nối database $conn = mysqli_connect('localhost', 'root', 'vertrigo', 'demo') or die ('Không thể kết nối đến CSDL'); mysqli_set_charset($conn, 'utf8'); // Lấy trang hiện tại $page = isset($_GET['page']) ? (int)$_GET['page'] : 1; // Kiểm tra trang hiện tại có bé hơn 1 hay không if ($page < 1) { $page = 1; } // Số record trên một trang $limit = 3; // Tìm start $start = ($limit * $page) - $limit; // Câu truy vấn // Trong câu truy vấn này chúng ta sẽ lấy limit tăng lên 1 // Lý do là vì ta không có viết code đếm record nên dựa vào tổng số kết quả trả về để: // - Nếu kết quả trả về bằng $limit + 1 thì còn phân trang // - Nếu kết quả trả về bé hơn $limit + 1 thì nghĩa là hết dữ liệu nên ngưng phân trang $sql = "select * from tb_customer limit $start,".($limit + 1); // Thực hiện câu truy vấn $query = mysqli_query($conn, $sql) or die ('Lỗi câu truy vấn'); // Duyệt kết quả rồi đưa vào mảng result $result = array(); while ($row = mysqli_fetch_array($query)) { // Thêm vào result array_push($result, $row); } // Nếu là request ajax thì trả kết quả JSON if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'){ // Mình sleep 1 giây để các bạn check nhé, khi sử dụng thì bỏ đoạn sleep này đi sleep(1); // Trả kết quả về cho ajax die (json_encode($result)); } else // Ngược lại thì hiển thị bình thường. Trường hợp này dùng load trong file list.php { $total = count($result); // Bỏ đi kết quả cuối cùng vì kết quả này dùng để check phân trang thôi for ($i = 0; $i < $total - 1; $i++) { echo '<div class="item">'; echo $result[$i]['id'].' - '.$result[$i]['name'].' - '.$result[$i]['website']; echo '</div>'; } } ?>
Trong phần comment mình đã giải thích khá kỹ rồi, riêng có một lưu ý với bạn là đoạn xuất danh sách ra màn hình có 2 trường hợp:
- Nếu request là ajax thì sẽ trả về danh sách dạng JSON để javascript xử lý dữ liệu và hiển thị ra
- Nếu request không phải ajax thì dùng code PHP show danh sách khách hàng ra luôn, trường hợp này dùng cho lần load đầu tiên ở file
list.php
File ajax pagination load more ajax.js
Nội dung file này như sau:
// Biến dùng kiểm tra nếu đang gửi ajax thì ko thực hiện gửi thêm var is_busy = false; // Biến lưu trữ trang hiện tại var page = 1; // Số record trên mỗi trang var record_per_page = 3; // Biến lưu trữ rạng thái phân trang var stopped = false; $(document).ready(function() { // Khi kéo scroll thì xử lý $('#load_more').click(function() { // Element append nội dung $element = $('#content'); // ELement hiển thị chữ loadding $button = $(this); // Nếu đang gửi ajax thì ngưng if (is_busy == true) { return false; } // Tăng số trang lên 1 page++; // Hiển thị loadding ... $button.html('LOADDING ...'); // Gửi Ajax $.ajax( { type: 'get', dataType: 'json', url: 'data.php', data: {page: page}, success: function(result) { var html = ''; // Trường hợp hết dữ liệu cho trang kết tiếp if (result.length <= record_per_page) { // Lặp dữ liêụ $.each(result, function (key, obj){ html += '<div>'+obj.id+' - '+obj.name+'-'+obj.website+'</div>'; }); // Thêm dữ liệu vào danh sách $element.append(html); // Xóa button $button.remove(); } else{ // Trường hợp còn dữ liệu cho trang kế tiếp // Lặp dữ liêụ, trường hợp này ta lặp bỏ đi phần record cuối cùng vì ta selec với limit + 1 $.each(result, function (key, obj){ if (key < result.length - 1){ html += '<div>'+obj.id+' - '+obj.name+'-'+obj.website+'</div>'; } }); // Thêm dữ liệu vào danh sách $element.append(html); } } }) .always(function() { // Sau khi thực hiện xong thì đổi giá trị cho button $button.html('LOAD MORE'); is_busy = false; }); }); });
Không giống như ví dụ trong bài srolling pagination là kết quả trả về HTML nên chỉ cần show ra, bài này kết quả ajax trả về JSON nên ta sẽ phải dùng vòng lặp each để xuất dữ liệu ra màn hình. Vẫn có 2 trường hợp là:
- Nếu kết quả trả về dư 1 record thì tức là còn dữ liệu cho trang tiếp, lúc này ta ko ẩn button và khi lặp phải bỏ phần tử cuối cùng
- Nếu kết quả trả về bé hơn hoặc bằng limit thì nghĩa là hết data, lúc này ta phải ẩn button load more.
Và đây là thành quả của chúng ta:
3. Lời kết
Lúc đầu mình không tính viết bài này vì nó cũng rất giống với bài Ajax Scrolling Pagination , chỉ khác là một bên có button load more và một bên không phải button. Tuy nhiên trong bài này mình sử dụng JSON để trả về khi gọi ajax nên sẽ hay hơn bài trước.