Tự động tải thêm dữ liệu khi page scroll bằng PHP + JQuery + Ajax + MySQL

Ajax 30/04/2016 07:00 1699
Hiện nay có một số website khi các bạn kéo xuống phía dưới cùng thì nó tự động load thêm dữ liệu. Facebook, Google, Twitter là những ví dụ điển hình chúng thực hiện hai thao tác, thứ nhất là kéo xuống sẽ load thêm, thứ hai là nó thiết lập sau một thời gian sẽ load thêm.

Như trong bài trước mình cũng đã chia sẻ với các bạn một phương pháp tải thêm dữ liệu sử dụng PHP, JQuery, Ajax và MySQL thì trong phương pháp đó khi bạn tải thêm dữ liệu thì bạn phải click vào một button nào đó. Bạn có thể xem lại bài Tải thêm dữ liệu sử dụng jQuery Ajax và PHP từ cơ sở dữ liệu. Trong bài viết này mình sẽ trình bày cách hệ thống tự động tải thêm dữ liệu khi người dùng kéo thanh scrollbar xuống cuối của màn hình.

Chúng ta sẽ đi từng phần một nhé.

  • Step 1: Chuẩn bị CSDL mình sẽ sử dụng bảng City(city_id,name).
  • Step 2: Tạo file hiển thị danh sách
  • Step 3: Viết JQuery Ajax xử lý khi người sử dụng kéo thanh scrollbar xuống cuối trang.

1. Tạo database

Trong bài viết này chúng ta sẽ tạo một bảng City lưu trữ danh sách các tỉnh/thành phố của nước ta.

DROP TABLE IF EXISTS `City`;
CREATE TABLE `City` (
  `city_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `country_id` int(10) unsigned NOT NULL DEFAULT '1',
  `name` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `alias` varchar(255) CHARACTER SET utf8 NOT NULL,
  `order_no` int(10) unsigned NOT NULL DEFAULT '0',
  `reg_date` int(10) NOT NULL,
  `upd_date` int(10) NOT NULL,
  `is_trash` tinyint(1) NOT NULL,
  PRIMARY KEY (`city_id`)
) ENGINE=INNODB AUTO_INCREMENT=478 DEFAULT CHARSET=latin1;

2. Thêm một vài record.

INSERT INTO `City` VALUES ('244', '1', 'Hồ Chí Minh', 'ho-chi-minh', '2', '0', '1399650921', '0');
INSERT INTO `City` VALUES ('271', '1', 'Cao Bằng', 'cao-bang', '27', '0', '1399651015', '0');
INSERT INTO `City` VALUES ('272', '1', 'Yên Bái', 'yen-bai', '29', '0', '1399651048', '0');
INSERT INTO `City` VALUES ('273', '1', 'Cần Thơ', 'can-tho', '28', '0', '1399651039', '0');
INSERT INTO `City` VALUES ('275', '1', 'Cà Mau', 'ca-mau', '31', '0', '1399651505', '0');

3. Tạo file hiển thị danh sách.

Ta sẽ có cấu trúc các file trong ví dụ như sau.

demo
|__configdb.php // Kết nối database
|__getData.php // File tiếp nhận, xử lý khi ajax gửi
|__index.php // File hiển thị danh sách
|__loading.gif

3.1 File configdb.php

Chứa thông tin và biến kết nối tới CSDL

$db_host = 'localhost';
$db_name = 'demo';
$db_user = 'root';
$db_pass = '';

// Kết nối tới CSDL
$dbconn = mysqli_connect($db_host, $db_user, $db_pass, $db_name);
mysqli_set_charset($dbconn,"utf8");
// Kiểm tra kết nối
if (mysqli_connect_errno($dbconn)) {
	echo "Không thể kết nối tới MySQL: " . mysqli_connect_error();
}

3.2 Xây dựng danh sách hiển thị những record ban đầu.

<?php
	require_once('dbconfig.php');
	
	// Số record hiển thị ban đầu
	$record_per_page = 10;
	
	// Tỉnh tổng số record có trong bảng
	$query = mysqli_query($dbconn,"SELECT COUNT(*) as totalRecords FROM City");
	$row = mysqli_fetch_assoc($query);
	$totalRecords = $row['totalRecords'];
	
	// Thực thi query để lấy dữ liệu ban đầu
	$sql = "SELECT * FROM City ORDER BY city_id ASC LIMIT 0,$record_per_page";
	$query = mysqli_query($dbconn,$sql);
?>

<?php if(mysqli_num_rows($query) > 0){ ?>
	<ul class="post-list">
	<?php  while($row = mysqli_fetch_array($query)){ ?>
		<li class="post-list__item" data-city_id="<?php echo $row['city_id']; ?>">
			<h3><?php echo '#' . $row['city_id'].'.' . $row['name']; ?></h3>
		</li>
	<?php } ?>
	</ul>
	<!-- Nếu tổng số record > số record ban đầu -->
	<?php if($totalRecords > $record_per_page){ ?>
	<div class="load-more" style="display:none">
		<img src="loading.gif"/>
	</div>
	<?php } ?>
	
<?php } ?>

Lưu ý: Trong mỗi vòng lặp mình đã gán cho nó một thuộc tính data-city_id để nhằm xác định được đâu là record cuối cùng đã được tải.

4. Mã JQuery + Ajax khi người dụng kéo scrollbar xuống cuối.

$(document).ready(function(){
    // Biến dùng kiểm tra xem page đã scroll chưa
    var alreadyScroll = false;
    $(window).scroll(function(){
        // Lấy ID cuối cùng của danh sách
        var lastID = $('.post-list__item:last').data('city_id');
        
        // Nếu màn hình đang ở dưới cuối thẻ thì thực hiện tải thêm dữ liệu.
        if ($(window).scrollTop() == $(document).height() - $(window).height()
        && alreadyScroll==false){
            // Gán page đã scroll
            alreadyScroll = true;
            $.ajax({
                type:'POST',
                url:'getData.php',
                data:'city_id='+lastID,
                beforeSend:function(html){
                    $('.load-more').show();
                },
                success:function(html){
                    // Ẩn nút more
                    $('.load-more').hide();
                    if(html.indexOf('_invaliddata') >=0){
                        // Trường hợp hết dữ liệu
                    }else{
                        alreadyScroll = false;
                        // Trường hợp còn dữ liệu
                        // Chèn dữ liệu tiếp sau phần từ cuối cùng
                        $('.post-list > .post-list__item:last').after(html);
                    }
                }
            });
        }
    });
});

Lưu ý:

alreadyScroll: Lưu trữ tính trạng xem người dùng đã kéo thanh scrollbar xuống cuối trang hay chưa? Nếu người dùng kéo rồi thì ngay lập tức biến này sẽ lưu lại quá trình từ lúc bắt đầu tới khi hoàn thành một quá trình gửi và nhận dữ liệu thành công hoặc tới khi hết dữ liệu.

lastID: Record cuối cùng xuất hiện trong danh sách đã được tải và các record tiếp tục được tải thêm sẽ phải lớn hơn hoặc nhỏ hơn nó tuy thuộc vào cách sắp xếp thứ tự của bạn được sử dụng trong.

5. Tạo file tiếp nhận yêu cầu của Ajax xử lý và trả về kết quả.

require_once('dbconfig.php');

// Lấy về ID lớn nhất đã được tải.
$city_id = $_POST['city_id'];

// Số record sẽ được load thêm
$limit = " LIMIT 0,5";

// Thực hiện câu truy vấn
$query = mysqli_query($dbconn,"SELECT * FROM City WHERE city_id>'$city_id' ORDER BY city_id ASC ".$limit);

// Mặc định là dữ liệu sẽ trống
$html = '_invaliddata';

// Hiển thị dữ liệu
if(mysqli_num_rows($query) > 0){
    $html = '';
    while($row = mysqli_fetch_array($query)){
        $html .= '<li class="post-list__item" data-city_id="'.$row['city_id'].'">
            <h3>#' . $row['city_id'].'.' . $row['name'] . '</h3>
        </li>';	
    }
}
#
echo $html;
die();

Lưu ý: Trong đoạn code trên mình sử dụng từ khóa _invaliddata để thông báo cho phía client là dữ liệu đã hết.Từ đó client khi phân tích kết quả trả về có từ khóa này sẽ ngắt sự kiện khi người dùng kéo thanh scrollbar tới cuối trang.

6. Tổng kết.

Với phương pháp này sẽ làm tăng tính khả dụng cho người dùng. Trên thực tế để mở rộng tính năng này chúng ta cần phải xem xét thêm hai trường hợp khi người dùng kéo thành scrollbar tới một điểm móc nào đó. Thường điểm móc đó được xác định nằm cuối của block body và trước của block footer. Và khi người dùng kéo thành scrollbar xuống cuối cùng của một box.

Xem Thêm

Profile photo of adminTheHalfHeart

B.V.T

Sinh ra và lớn nên ở Bắc Giang. Hiện tại thì tôi đang là một lập trình viên tại VietISO. Tôi lập website này với mục đích là bookmark những gì tôi đã đọc qua và mong muốn chia sẻ những gì tôi biết.