PHP AJAX
CÁC CHỦ ĐỀ
BÀI MỚI NHẤT
MỚI CẬP NHẬT

Search ajax Autocomplete có phân trang

Đây là bài thứ 12 trong loạt serie ajax toàn tập. Nếu như bạn đã đọc đến bài này thì tôi tin rằng bạn đã nắm vững được ajax jquery rồi, nên để nâng cao hơn xíu hôm nay tôi sẽ hướng dẫn làm chức năng search autocomplete ajax có phân trang.

test php

banquyen png
Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.

Search autocomplete là gì? Nếu bạn chưa biết nó là gì thì tôi xin trích dẫn thế này, chắc hẳn bạn đã từng vào một số website có chức năng search và khi bạn nhập nội dung vào nó tự động lấy nội dung và hiển thị cho bạn mà không cần phải reload trang. Đây là chức năng rất thân thiện với người dùng nên nếu áp dụng vào website thì tuyệt cú mèo. 

Kết quả của bài này ta có form như hình sau:

search autocomplete

1. Xây dựng database

Trước tiên bạn cần tạo một database tên test và chạy nội dung sql bên dưới để tạo bảng và thêm một số data.

Bài viết này được đăng tại [free tuts .net]

 

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";

CREATE TABLE IF NOT EXISTS `member` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(30) DEFAULT NULL,
  `email` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=30 ;

INSERT INTO `member` (`id`, `username`, `email`) VALUES
(1, 'thehalfheart', 'thehalfheart@gmail.com'),
(2, 'freetuts', 'freetuts.net@gmail.com'),
(3, 'kingston', 'kingston@gmail.com'),
(4, 'cafeviet', 'cafeviet@gmail.com'),
(5, 'emailer', 'emailer@gmail.com'),
(6, 'domain', 'domain@gmail.com'),
(7, 'root', 'root@gmail.com'),
(8, 'admin', 'admin@gmail.com'),
(9, 'supper', 'supper@gmail.com'),
(10, 'hoconline', 'hoconline@gmail.com'),
(11, 'codon', 'codon@gmail.com'),
(12, 'thesky', 'thesky@gmail.com'),
(13, 'khoanguyen', 'khoanguyen@gmail.com'),
(14, 'trinhut', 'trinhut@gmail.com'),
(15, 'sanhot', 'sanhot@gmail.com'),
(16, 'nammoitetden', 'nammoitetden@gmail.com'),
(17, 'nhatkydoitoi', 'nhatkydoitoi@gmail.com'),
(18, 'freetutsonline', 'freetutsonline@gmail.com'),
(19, 'sinhthoi', 'sinhthoi@gmail.com'),
(20, 'xatoiradioco', 'xatoiradioco@gmail.com'),
(21, 'emailaothu1', 'emailaothu1@gmail.com'),
(22, 'emailaothu2', 'emailaothu2@gmail.com'),
(23, 'emailaothu3', 'emailaothu3@gmail.com'),
(24, 'emailaothu4', 'emailaothu4@gmail.com'),
(25, 'emailaothu5', 'emailaothu5@gmail.com'),
(26, 'emailaothu6', 'emailaothu6@gmail.com'),
(27, 'emailaothu7', 'emailaothu7@gmail.com'),
(28, 'emailaothu8', 'emailaothu8@gmail.com'),
(29, 'emailaothu9', 'emailaothu9@gmail.com');

 

2. Xây dựng thư viện phân trang

Vì trong bài search autocomplete ajax này tôi có phân trang nên bắt buộc phải xây dựng lớp phân trang rồi :D. Bạn tạo file pagination.php và copy nội dung bên dưới vào:

 

class Pagination {

    protected $_config = array(
        'current_page'  => 1, // Trang hiện tại
        'total_record'  => 1, // Tổng số record
        'total_page'    => 1, // Tổng số trang
        'limit'         => 10, // limit
        'start'         => 0, // start
        'link_full'     => '', // Link full có dạng như sau: domain/com/page/{page}
        'link_first'    => '', // Link trang đầu tiên
        'range'         => 9, // Số button trang bạn muốn hiển thị
        'min'           => 0, // Tham số min
        'max'           => 0  // tham số max, min và max là 2 tham số private
    );
    
    function init($config = array()) 
    {
        foreach ($config as $key => $val) {
            if (isset($this->_config[$key])) {
                $this->_config[$key] = $val;
            }
        }
        
        if ($this->_config['limit'] < 0) {
            $this->_config['limit'] = 0;
        }

        $this->_config['total_page'] = ceil($this->_config['total_record'] / $this->_config['limit']);

        if (!$this->_config['total_page']) {
            $this->_config['total_page'] = 1;
        }

        if ($this->_config['current_page'] < 1) {
            $this->_config['current_page'] = 1;
        }

        if ($this->_config['current_page'] > $this->_config['total_page']) {
            $this->_config['current_page'] = $this->_config['total_page'];
        }

        $this->_config['start'] = ($this->_config['current_page'] - 1) * $this->_config['limit'];

        $middle = ceil($this->_config['range'] / 2);

        if ($this->_config['total_page'] < $this->_config['range']) {
            $this->_config['min'] = 1;
            $this->_config['max'] = $this->_config['total_page'];
        }
        else {
            $this->_config['min'] = $this->_config['current_page'] - $middle + 1;

            $this->_config['max'] = $this->_config['current_page'] + $middle - 1;

            if ($this->_config['min'] < 1) {
                $this->_config['min'] = 1;
                $this->_config['max'] = $this->_config['range'];
            }

            else if ($this->_config['max'] > $this->_config['total_page']) {
                $this->_config['max'] = $this->_config['total_page'];
                $this->_config['min'] = $this->_config['total_page'] - $this->_config['range'] + 1;
            }
        }
    }
    
    function get_config($key){
        return $this->_config[$key];
    }
    
    private function __link($page) {
        if ($page <= 1 && $this->_config['link_first']) {
            return $this->_config['link_first'];
        }
        return str_replace('{page}', $page, $this->_config['link_full']);
    }

    function html() {
        $p = '';
        if ($this->_config['total_record'] > $this->_config['limit']) {
            $p = '<ul>';

            // Nút prev và first
            if ($this->_config['current_page'] > 1) {
                $p .= '<li><a href="' . $this->__link('1') . '" title="1">First</a></li>';
                $p .= '<li><a href="' . $this->__link($this->_config['current_page'] - 1) . '" title="'.($this->_config['current_page'] - 1).'">Prev</a></li>';
            }

            // lặp trong khoảng cách giữa min và max để hiển thị các nút
            for ($i = $this->_config['min']; $i <= $this->_config['max']; $i++) {
                // Trang hiện tại
                if ($this->_config['current_page'] == $i) {
                    $p .= '<li><span>' . $i . '</span></li>';
                } else {
                    $p .= '<li><a href="' . $this->__link($i) . '" title="'.$i.'">' . $i . '</a></li>';
                }
            }

            // Nút last và next
            if ($this->_config['current_page'] < $this->_config['total_page']) {
                $p .= '<li><a href="' . $this->__link($this->_config['current_page'] + 1) . '" title="'.($this->_config['current_page'] + 1).'">Next</a></li>';
                $p .= '<li><a href="' . $this->__link($this->_config['total_page']) . '" title="'.$this->_config['total_page'].'">Last</a></li>';
            }
            $p .= '</ul>';
        }
        return $p;
    }
}

 

Nếu bạn chưa biết cách viết thư viện phân trang thì có thể tham khảo hai bài sau:

3. Xây dựng model xử lý database

Để cho tiện lợi trong quá trình xử lý database để search autocomplete thì tôi sẽ xây dựng một file chuyên dùng để lấy danh sách và truy vấn theo tham số search truyền vào. Bạn tạo file database.php và copy nội dung bên dưới vào.

 

// Khai báo biến toàn cục kết nối
global $conn;
 
// Hàm kết nối database
function connect(){
    global $conn;
    $conn = mysqli_connect('localhost', 'root', 'vertrigo', 'test') or die ('{error:"bad_request"}');
}
 
// Hàm đóng kết nối
function disconnect(){
    global $conn;
    if ($conn){
        mysqli_close($conn);
    }
}
 
// Hàm đếm tổng số thành viên
function count_all_member($username = '')
{
    global $conn;
    
    if ($username){
        $query = mysqli_query($conn, 'select count(*) as total from member where username like '%'.mysql_escape_string($username).'%'');
    }
    else{
        $query = mysqli_query($conn, 'select count(*) as total from member');
    }
    
    if ($query){
        $row = mysqli_fetch_array($query, MYSQLI_ASSOC);
        return $row['total'];
    }
    return 0;
}
 
// Lấy danh sách thành viên
function get_all_member($username = '', $limit = 10, $start = 0)
{
    global $conn;
    
    if ($username){
        $sql = 'select * from member  where username like '%'.mysql_escape_string($username).'%' limit '.(int)$start . ','.(int)$limit;
    }
    else{
        $sql = 'select * from member limit '.(int)$start . ','.(int)$limit;
    }
    
    $query = mysqli_query($conn, $sql);
     
    $result = array();
     
    if ($query)
    {
        while ($row = mysqli_fetch_array($query, MYSQLI_ASSOC)){
            $result[] = $row;
        }
    }
     
    return $result;
}

 

Trong file tôi đã comment rất kỹ rồi nên ko giải thích gì thêm

4. Xây dựng hàm lấy danh sách search autocomplete và trả về chuỗi JSON

Bạn tạo file get_data.php và copy nội dung sau:

 

// Require Lib
require "database.php";
require "pagination.php";

// Lấy thong tin lọc
$username = isset($_GET['username']) ? $_GET['username'] : '';

// Lấy trang hiện tại
$page = isset($_GET['page']) ? $_GET['page'] : 1;

// Khởi tạo đối tượng Pagination mới
$pagination = new Pagination();

// Kết nối db
connect();

// Cấu hình thông số phân trang
$pagination->init(array(
    'current_page'  => $page,
    'total_record'  => count_all_member($username),
    'link_full'     => 'get_data.php?page={page}&username='.$username,
    'link_first'    => 'get_data.php'
));

// Lấy limit và Start
$limit = $pagination->get_config('limit');
$start = $pagination->get_config('start');

// Lấy danh sách người dùng
$data = get_all_member($username, $limit, $start);

// Ngắt kết nối
disconnect();

// Trả kết quả cho client
die (json_encode(array(
    'data' => $data,
    'paging' => $pagination->html()
)));

 

Các bạn lưu ý là tôi trả về kết quả là chuỗi JSON nên ở file xử lý ajax ta phải truyền dataType là JSON nhé.

5. Xây dựng trang hiển thị danh sách và search autocomplete

Bạn tạo file index.php và copy nội dung sau:

 

<!DOCTYPE html>
<html>
    <head>
        <title>Tìm kiếm theo ajax</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <script language="javascript" src="http://code.jquery.com/jquery-2.0.0.min.js"></script>
        <style>
            html{width:900px; margin:0px auto}
            input{padding: 5px}
            li{float:left; margin: 3px; border: solid 1px gray;}
            a{padding: 5px;}
            span{display:inline-block; padding: 0px 3px; background: blue; color:white}
            li{list-style: none; padding: 0px 5px}
        </style>
        <script language="javascript">
            $(document).ready(function()
            {
                // Biến lưu trữ thông số tìm kiếm
                var data = {
                    username : '', // tên đăng nhập
                    page : 1 // trang cần đến, dùng trong trường hợp có phân trang
                };
                
                // Khi nhập dữ liệu thì gọi ajax
                $('#q').keyup(function(){   
                    data.username = $(this).val();
                    search();
                });
                
                // Hàm xử lý khi click vào phân trang
                $('#content').on('click', 'a', function (){
                   data.page = $(this).attr('title');
                   search();
                   return false;
                });
                
                // Hàm gửi ajax
                function search()
                {
                    $.ajax({
                        url : 'get_data.php',
                        data : data,
                        type : 'get',
                        dataType : 'json',
                        success : function (result)
                        {
                            // Nếu dữ liệu trả về đúng thì mới xử lý
                            if (result.hasOwnProperty('data') && result.hasOwnProperty('paging'))
                            {
                                var html = '<table border="1" cellspacing="0" cellpadding="5">';
                                    html += '<tr style="font-weight:bold">';
                                        html += '<td>Username</td>';
                                        html += '<td>Email</td>';
                                    html += '</tr>';
                                    
                                    // Lặp qua từng record và gán html
                                    $.each(result['data'], function (index, item){
                                        html += '<tr>';
                                            html += '<td>'+item.username+'</td>';
                                            html += '<td>'+item.email+'</td>';
                                        html += '</tr>';
                                    });

                                html += '</table>';
                                
                                // Thêm html paging
                                html += result['paging'];
                                
                                // Gán kết quả vào div#content
                                $('#content').html(html);
                            }
                        }
                    });
                }
            });
        </script>
    </head>
    <body>
        <input type="text" id="q" value="" placeholder="Nhập nội dung muốn tìm kiếm" size="50"/>
        <div id="content" style="margin-top: 20px;"></div>
    </body>
</html>

 

Trong file này thẻ div#content dùng để gán data vào, và tôi đã sử dụng hàm html() jquery để gán.

Trong đoạn ajax tôi có định nghĩa một hàm search dùng để gửi ajax và tôi cũng có gán 2 sự kiện khi keyUp vào ô search và khi click vào phân trang. Trong phần comment tôi đã trình bày rõ ràng rồi nên tôi cũng ko nói gì thêm nữa nhé.

6. Lời kết

Trong bài này quan trọng nhất là đoạn code xử lý jquery ajax search autocomplete, các bạn cố gắng gõ và làm theo nhé, copy nhưng cũng phải hiểu thì mới học tốt được. Còn một vấn đề tôi không trình bày, đó là khi ta nhập từ search nó gửi rất nhiều request, mỗi ký tự một request nên không được hay lắm, để giải quyết vấn đề này ta sẽ xây dựng hệ thống timer, nghĩa là khi người dùng dừng không gõ chừng 0.5 giây ta mới gửi, như vậy sẽ giảm được số request gửi lên server. Vấn đề này ta sẽ học ở bài tiếp they delay keyup event.

Danh sách file tải về

Tên file tải về Pass giải nén
Tải bài học định dạng PDF freetuts.net hoặc gameportable.net

Cùng chuyên mục:

Hàm key_exists() trong PHP

Hàm key_exists() trong PHP

Cách sử dụng key_exists() trong PHP

Hàm mysqli_fetch_row() trong PHP

Hàm mysqli_fetch_row() trong PHP

Cách sử dụng mysqli_fetch_row() trong PHP

Hàm end() trong PHP

Hàm end() trong PHP

Cách sử dụng end() trong PHP

Hàm mysqli_field_count() trong PHP

Hàm mysqli_field_count() trong PHP

Cách sử dụng mysqli_field_count() trong PHP

Hàm count() trong PHP

Hàm count() trong PHP

Cách sử dụng count() trong PHP

Hàm mysqli_field_seek() trong PHP

Hàm mysqli_field_seek() trong PHP

Cách sử dụng mysqli_field_seek() trong PHP

Hàm compact() trong PHP

Hàm compact() trong PHP

Cách sử dụng compact() trong PHP

Hàm mysqli_field_tell() trong PHP

Hàm mysqli_field_tell() trong PHP

Cách sử dụng mysqli_field_tell() trong PHP

Hàm array_values() trong PHP

Hàm array_values() trong PHP

Cách sử dụng array_values() trong PHP

Hàm mysqli_free_result() trong PHP

Hàm mysqli_free_result() trong PHP

Cách sử dụng mysqli_free_result() trong PHP

Hàm array_unshift() trong PHP

Hàm array_unshift() trong PHP

Cách sử dụng array_unshift() trong PHP

Hàm mysqli_get_charset() trong PHP

Hàm mysqli_get_charset() trong PHP

Cách sử dụng mysqli_get_charset() trong PHP

Hàm array_shift() trong PHP

Hàm array_shift() trong PHP

Cách sử dụng array_shift() trong PHP

Hàm mysqli_get_client_stats() trong PHP

Hàm mysqli_get_client_stats() trong PHP

Cách sử dụng mysqli_get_client_stats() trong PHP

Hàm array_unique() trong PHP

Hàm array_unique() trong PHP

Cách sử dụng array_unique() trong PHP

Hàm mysqli_get_client_version() trong PHP

Hàm mysqli_get_client_version() trong PHP

Cách sử dụng mysqli_get_client_version() trong PHP

Hàm array_uintesect() trong PHP

Hàm array_uintesect() trong PHP

Cách sử dụng array_uintesect() trong PHP

Hàm mysqli_get_connection_stats() trong PHP

Hàm mysqli_get_connection_stats() trong PHP

Cách sử dụng mysqli_get_connection_stats() trong PHP

Hàm array_sum() trong PHP

Hàm array_sum() trong PHP

Cách sử dụng array_sum() trong PHP

Hàm mysqli_get_host_info() trong PHP

Hàm mysqli_get_host_info() trong PHP

Cách sử dụng mysqli_get_host_info() trong PHP

Top