即使JSON数组包含“对象”,实时搜索也会返回“未定义”

时间:2019-07-10 20:33:05

标签: javascript php ajax search prepared-statement

我面临通过MySQL数据库通过AJAX请求检索实时用户数据的问题。当前,PHP脚本(“ live_search.php”)仅返回值“ object”,因此变量显示为“ undefined”。

这是结果: /Users/Jakob/Desktop/Screenshot

enter image description here

我猜问题出在PHP脚本中。

<input type="text" name="username_search" id="textbox" />
<div id="result"></div>

<script type="text/javascript">

        var textBox = document.getElementById('textbox'),
            resultContainer = document.getElementById('result')

        // keep this global to abort it if already a request is running even textbox is upated
        var ajax = null;
        var loadedUsers = 0; // number of users shown in the results

        textBox.onkeyup = function() {
            // "this" refers to the textbox
            var val = this.value;

            // trim - remove spaces in the begining and the end
            val = val.replace(/^\s|\s+$/, "");

            // check if the value is not empty
            if (val !== "") {
                // search for data
                searchForData(val);
            } else {
                // clear the result content
                clearResult();
            }
        }


        function searchForData(value, isLoadMoreMode) {
            // abort if ajax request is already there
            if (ajax && typeof ajax.abort === 'function') {
                ajax.abort();
            }

            // nocleaning result is set to true on load more mode
            if (isLoadMoreMode !== true) {
                clearResult();
            }

            // create the ajax object
            ajax = new XMLHttpRequest();
            // the function to execute on ready state is changed
            ajax.onreadystatechange = function() {
                if (this.readyState === 4 && this.status === 200) {
                    try {
                        var json = JSON.parse(this.responseText)
                        window.alert(json);
                    } catch (e) {
                        noUsers();
                        return;
                    }

                    if (json.length === 0) {
                        if (isLoadMoreMode) {
                            alert('No more to load');
                        } else {
                            noUsers();
                        }
                    } else {
                        showUsers(json);
                    }

                }
            }
            // open the connection
            ajax.open('GET', 'live_search.php?username_search=' + value + '&startFrom=' + loadedUsers , true);
            // send
            ajax.send();
        }

        function showUsers(data) {
            // the function to create a row
            function createRow(rowData) {
                // creating the wrap
                var wrap = document.createElement("div");
                // add a class name
                wrap.className = 'row'

                // name holder
                var name = document.createElement("span");
                name.innerHTML = rowData.name;

                var link = document.createElement("span");
                link.innerHTML = rowData.link;

                wrap.appendChild(name);
                wrap.appendChild(link);

                // append wrap into result container
                resultContainer.appendChild(wrap);
            }

            // loop through the data
            for (var i = 0, len = data.length; i < len; i++) {
                // get each data
                var userData = data[i];
                // create the row (see above function)
                createRow(userData);
            }

            //  create load more button
            var loadMoreButton = document.createElement("span");
            loadMoreButton.innerHTML = "Load More";
            // add onclick event to it.
            loadMoreButton.onclick = function() {
                // searchForData() function is called in loadMoreMode
                searchForData(textBox.value, true);
                // remove loadmorebutton
                this.parentElement.removeChild(this);
            }
            // append loadMoreButton to result container
            resultContainer.appendChild(loadMoreButton);

            // increase the user count
            loadedUsers += len;
        }

        function clearResult() {
            // clean the result <div>
            resultContainer.innerHTML = "";
            // make loaded users to 0
            loadedUsers = 0;
        }

        function noUsers() {
            resultContainer.innerHTML = "No Users";
        }

    </script>

// php脚本

<?php
require 'db.php';
session_start();

$username = $_GET['username_search'];
$startFrom = $_GET['startFrom'];

$username = trim(htmlspecialchars($username));
$startFrom = filter_var($startFrom, FILTER_VALIDATE_INT);

// make username search friendly
$like = '%' . strtolower($username) . '%'; // search for the username, case-insensitive
$statement = $mysqli -> prepare('
    SELECT first_name, url_user FROM user 
    WHERE lower(first_name) LIKE ? 
    ORDER BY INSTR(first_name, ?), first_name
    LIMIT 6 OFFSET ?
');

if (
    // $mysqli -> prepare returns false on failure, stmt object on success
    $statement &&
    // bind_param returns false on failure, true on success
    $statement -> bind_param('ssi', $like, $username, $startFrom ) &&
    // execute returns false on failure, true on success
    $statement -> execute() &&
    // same happens in store_result
    $statement -> store_result() &&
    // same happens here
    $statement -> bind_result($first_name, $url_user)
) {
    // I'm in! everything was successful.

    // new array to store data
    $array = [];


    while ($statement -> fetch()) {
        $array[] = [
            'first_name' => $first_name,
            'url_user' => $url_user
        ];
    }

    echo json_encode($array);
    exit();


}

预期结果是进行实时搜索,实时返回用户数据。另外,我的目标是使该行成为指向相应用户的链接(给定url_link)。加载更多按钮是次要按钮,并不是太重要。

2 个答案:

答案 0 :(得分:1)

PHP不返回对象。当您alert使用JSON时,变量json是一个对象。您的未定义输出来自以下行:

// name holder
var name = document.createElement("span");
name.innerHTML = rowData.name;

var link = document.createElement("span");
link.innerHTML = rowData.link;

您的PHP返回具有属性first_nameurl_user的对象数组。您无需在两者之间的任何位置更改它们,因此namelink是未定义的。

此外,您的PHP过于肿,例如,您可以使其变得更简单:

<?php

// put this line inside the db.php before making the mysqli connection
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
require 'db.php';
session_start();

$username = $_GET['username_search'];
$startFrom = $_GET['startFrom'];

$username = trim(htmlspecialchars($username)); // <- don't do this, it hurts your data
$startFrom = filter_var($startFrom, FILTER_VALIDATE_INT);

// make username search friendly
$like = '%' . strtolower($username) . '%'; // search for the username, case-insensitive
$statement = $mysqli->prepare('
    SELECT first_name, url_user FROM user 
    WHERE lower(first_name) LIKE ? 
    ORDER BY INSTR(first_name, ?), first_name
    LIMIT 6 OFFSET ?
');

$statement->bind_param('ssi', $like, $username, $startFrom);
$statement->execute();
$array = $statement->get_result()->fetch_all();
echo json_encode($array);

答案 1 :(得分:0)

<input type="text" name="username_search" id="textbox" />
<div id="result"></div>

<!-- Script for ajax get request for the live search -->
<script type="text/javascript">

    var textBox = document.getElementById('textbox'),
        resultContainer = document.getElementById('result')

    // keep this global to abort it if already a request is running even textbox is upated
    var ajax = null;
    var loadedUsers = 0; // number of users shown in the results

    textBox.onkeyup = function() {
        // "this" refers to the textbox
        var val = this.value;

        // trim - remove spaces in the begining and the end
        val = val.replace(/^\s|\s+$/, "");

        // check if the value is not empty
        if (val !== "") {
            // search for data
            searchForData(val);
        } else {
            // clear the result content
            clearResult();
        }
    }


    function searchForData(value, isLoadMoreMode) {
        // abort if ajax request is already there
        if (ajax && typeof ajax.abort === 'function') {
            ajax.abort();
        }

        // nocleaning result is set to true on load more mode
        if (isLoadMoreMode !== true) {
            clearResult();
        }

        // create the ajax object
        ajax = new XMLHttpRequest();
        // the function to execute on ready state is changed
        ajax.onreadystatechange = function() {
            if (this.readyState === 4 && this.status === 200) {
                try {
                    var json = JSON.parse(this.responseText)
                } catch (e) {
                    noUsers();
                    return;
                }

                if (json.length === 0) {
                    if (isLoadMoreMode) {
                        alert('No more to load');
                    } else {
                        noUsers();
                    }
                } else {
                    showUsers(json);
                }


            }
        }
        // open the connection
        ajax.open('GET', 'live_search.php?username_search=' + value + '&startFrom=' + loadedUsers , true);
        // send
        ajax.send();
    }

    function showUsers(data) {
        // the function to create a row
        function createRow(rowData) {
            // creating the wrap
            var wrap = document.createElement("div");
            // add a class name
            wrap.className = 'row'

            // name holder
            var first_name = document.createElement("span");
            first_name.innerHTML = rowData[0];

            var url_user = document.createElement("span");
            url_user.innerHTML = rowData[1];

            wrap.appendChild(first_name);
            wrap.appendChild(url_user);

            // append wrap into result container
            resultContainer.appendChild(wrap);
        }

        // loop through the data and call createRow function
        for (var i = 0, len = data.length; i < len; i++) {
            // get each data
            var userData = data[i];
            // create the row (see above function)
            createRow(userData);
        }

        //  create load more button
        var loadMoreButton = document.createElement("span");
        loadMoreButton.innerHTML = "Load More";
        // add onclick event to it.
        loadMoreButton.onclick = function() {
            // searchForData() function is called in loadMoreMode
            searchForData(textBox.value, true);
            // remove loadmorebutton
            this.parentElement.removeChild(this);
        }
        // append loadMoreButton to result container
        resultContainer.appendChild(loadMoreButton);

        // increase the user count
        loadedUsers += len;
    }

    function clearResult() {
        // clean the result <div>
        resultContainer.innerHTML = "";
        // make loaded users to 0
        loadedUsers = 0;
    }

    function noUsers() {
        resultContainer.innerHTML = "Sorry, no user found";
    }


</script>

  

php脚本

    <?php

require 'db.php';
session_start();

$username = $_GET['username_search'];
$startFrom = $_GET['startFrom'];

$username = trim(htmlspecialchars($username)); // <- don't do this, it hurts your data
$startFrom = filter_var($startFrom, FILTER_VALIDATE_INT);

// make username search friendly
$like = '%' . strtolower($username) . '%'; // search for the username, case-insensitive
$statement = $mysqli->prepare('
    SELECT first_name, url_user FROM user 
    WHERE lower(first_name) LIKE ? 
    ORDER BY INSTR(first_name, ?), first_name
    LIMIT 6 OFFSET ?
');

$statement->bind_param('ssi', $like, $username, $startFrom);
$statement->execute();
$array = $statement->get_result()->fetch_all();
echo json_encode($array);
  

感谢@Dharman