Tạo công cụ tìm kiếm bằng Jquery - Ajax - PHP

Hơn một năm rồi mới có dịp ngồi viết bài trên blog. Hôm này trời đẹp hơn hôm qua và việc cũng nhiều hơn hôm kia. Nhưng nó không liên quan gì đến bài viết ngày hôm nay cả!

Có một ông bạn đang cần tài liệu về tạo công cụ tìm kiếm bằng Ajax. Nên mình sẽ viết bài viết này như một tài liệu hướng dẫn làm cái chức năng này với Jquery Ajax còn server dùng PHP. Ngôn ngữ trên server là gì thì không quan trọng, quan trọng là server truy xuất được dữ liệu từ cơ sở dữ liệu theo từ khóa tìm kiếm và trả về dưới dạng Json.

Ở đoạn trên mình có đề cập tới các từ "Ajax, Jquery Ajax, Json" mấy cài này là gì thì mình không giải thích ở đây vì nó rất dài dòng. Nên để hiểu sâu hơn, ở đây mình có một vài đường link :


Chuẩn bị dữ liệu

Đầu tiên cần chuẩn bị phía server : Tạo CSDL, tạo server nhận từ khóa và trả về danh sách kết quả lấy trong CSDL tạm gọi là searchAPI.

Ở đây mình dùng MySQL :
Tạo cơ sở dữ liệu : 
CREATE SCHEMA `search_ajax_db` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Tạo một bảng sản phẩm đơn giản:
CREATE TABLE `search_ajax_db`.`products` (
  `idproducts` INT NOT NULL AUTO_INCREMENT,
  `product_name` VARCHAR(255) NULL,
  `price` FLOAT NULL,
  `quantity` INT NULL,
  PRIMARY KEY (`idproducts`))
ENGINE = InnoDB;

Bây giờ cần chèn dữ liệu cho nó, nhiều nhiều một chút. Nhưng nhập bằng tay thì chắc gãy tay cũng chả được bao nhiêu. Nên chúng ta lên trang sau : https://mockaroo.com/ để tạo dữ liệu ảo.



Chọn các tên cột giống như bảng vừa tạo, định dạng là SQL, tên bảng giống tên bảng vừa tạo.
Tải dữ liệu về có một file sql : search_ajax_db.products.sql import vào CSDL:
File sql cho ai lười: https://vipshare.co/u/yfspi1rpsi (link die thì kêu bên dưới nhớ)

Sau khi import vào chúng ta được bảng dữ liệu 1000 hàng ngon lành:



Rồi tiếp theo cần viết một câu SQL để tìm kiếm sản phẩm:
SELECT * FROM search_ajax_db.products where product_name like "%{keyword}%";
Thay {keyword} bằng từ khóa cần tìm kiếm là xong!

Xây dựng server searchAPI

Tiếp đến là server! Phần này làm bằng ngôn ngữ nào thì làm kiểu của ngôn ngữ đó thôi, đáp ứng được ý đồ của mình được được:


Code file server PHP:
    $servername = "localhost";
    $username = "root";
    $password = "tienanh";
    $dbname = "search_ajax_db";
    
    $keyword = "";
    if(isset($_GET['keyword'])){
        $keyword = $_GET['keyword'];
    }
    
    // Create connection
    $conn = new mysqli($servername, $username, $password, $dbname) or die(mysql_error());
    // Check connection
    if ($conn->connect_error) {
         die("Connection failed: " . $conn->connect_error);
    }
    
    // Lấy resultProducts
    $resultProducts = $conn->query("SELECT * FROM search_ajax_db.products where product_name like '%$keyword%' limit 10;");
    $myProducts = array();
    while($row = $resultProducts->fetch_array(MYSQLI_ASSOC)) {
        $myProducts[] = $row;
    }

    header('Content-Type: application/json');
    echo json_encode($myProducts, JSON_UNESCAPED_UNICODE);
    
    $conn->close();
Bây giờ chỉ cần truy cập vào địa chỉ local của server, ở đây là http://localhost/search.php?keyword=xxx là sẽ nhận được dữ liệu trả về dạng Json.

Xây dựng Client

Xong server rồi! tiến tới làm một cái giao diện có một ô input để nhập từ khóa vào, sau đó dùng jquery ajax gửi keyword lên server và nhận dữ liệu trả về đổ ra giao diện!

Mẫu HTML:
<html>
    <head>
        <meta charset="utf-8"/>
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
        <style>
        </style>
    </head>
    <body>
        
        <form class="form" style="margin: 10% 20%">
            <h1 class="header-title">Tìm kiếm sản phẩm</h1>
            <div class="form-group" style="position: relative">
               <input class="form-control mr-sm-2 search-input" style="margin-bottom: 5px;" type="search" placeholder="Nhập sản phẩm muốn tìm!" aria-label="Search">      
               <div class="result-search-box p-2" style="position: absolute; top: 40px; width: 100%; min-height: 50px;z-index: 9; display: none; border: dashed 1px gray">
                  <code>Kết quả tìm kiếm :</code>             
                  <div class="list-result-search mt-2"></div>
               </div>
            </div>
         </form>
         <script
         src="https://code.jquery.com/jquery-3.3.1.min.js"
         integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
         crossorigin="anonymous"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
        <!-- Nhớ gắn đoạn script bên dưới vào đây -->
    </body>
</html>

Code javascript:
var typingTimer;// bộ đếm
var doneTypingInterval = 500;  //time in ms, thời gian chờ gõ phím
var $input = $('.search-input'); // selector ô input
var url = window.location; // lấy cái địa chỉ hiện tại
var historykey = ""; // lưu lại từ khóa cũ

//khi gõ xong 1 phím tạo một khoảng chờ nhỏ nếu không bị clear sẽ gọi hàm thực thi
$input.on('keyup', function () {
    clearTimeout(typingTimer);
    typingTimer = setTimeout(doneTyping, doneTypingInterval);
});

//khi nhấn phím xuống xóa thời gian chờ đã tạo ra ở trên
$input.on('keydown', function () {
    clearTimeout(typingTimer);
});

//on không có thay đổi về nội dung trong ô input thì mới tạo request
$input.on('change', function () {
    if (historykey !== $input.val())
        doneTyping();
});
// đặt chuột vào ô input cũng cần check xem dữ liệu có khác không
$input.focus(function () {
    if (historykey !== $input.val())
        doneTyping();
});

//hàm này thực thi sau khi gõ phím doneTypingInterval ms
function doneTyping() {
    historykey = $input.val();
    $('.list-result-search').html("");
    if ($input.val()) {
        $('.result-search-box').slideDown(50);
        $.get(url.origin + "/search.php?keyword=" + $input.val(), function (result, status) {
            if (result.length) {
                result.forEach(function (currentValue, index) {
                    $('.list-result-search')
                        .append('<div>' + currentValue.product_name + ' |  ' + currentValue.price + ' vnđ </div>');
                });
            } else {
                $('.list-result-search').html("<p class='w3-padding'>Không tìm thấy kết quả nào cho <i>\"" + $input.val() + "\"</i></p>");
            }
        });

    } else {
        $('.result-search-box').slideUp();
    }
} // End typingDone

Thành quả của chúng ta :

Với cái mớ code trên kia theo mình thì nếu ngồi đọc lại vài lượt thì cũng dễ hiểu thôi đã comment tương đối rồi, nhưng để ngồi giải thích thì lại hơi mất thời gian lên chịu khó đọc anh em nhé! Chỉ cần nắm được đoạn này thôi:


$.get(url.origin + "/search.php?keyword=" + $input.val(), function (result, status) {
    if (result.length) {
        result.forEach(function (currentValue, index) {
            $('.list-result-search')
                 .append('<div>' + currentValue.product_name + ' |  ' + currentValue.price + ' vnđ </div>');
            });
    } else {
        $('.list-result-search').html("<p class='w3-padding'>Không tìm thấy kết quả nào cho <i>\"" + $input.val() + "\"</i></p>");
    }
 });

Đây là đoạn dùng Ajax để gửi từ khóa và kéo dữ liệu từ server về!
OK đến đây thôi! chúc các bạn thành công.



Nhận xét

Bài đăng phổ biến từ blog này

Câu chuyện kiếm việc làm trên upwork

4 Năm Đã Trôi Qua

Không có điều kỳ diệu nào - Nhưng chưa phải là kết thúc