Thứ Năm, 24 tháng 12, 2015

Ajax 15

Untitled Document

Bài 15: jQuery Ajax pagination load more với PHP và MYSQL
 0 
 Google +0 

  0
Đăng bởi: TheHalfHeart - Vào ngày: 10-12-2014 - Chuyên mục: PHP - View: 5009
Download Demo
Một số website có chức năng là 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 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 với jquery và PHP

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', 'freetuts.net'),
(2, 'Trương Phúc Hoài Minh', 'freetuts.net'),
(3, 'Đặng Văn Chương', 'freetuts.net'),
(4, 'Trương Tấn Thành', 'freetuts.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:
load-more-pagination-ajax.png


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.

0 nhận xét: