Живой поиск возвращает «неопределенный», хотя массив JSON содержит «объекты» - PullRequest
0 голосов
/ 10 июля 2019

У меня возникают проблемы с получением пользовательских данных в режиме реального времени через запрос AJAX из базы данных MySQL. В настоящее время PHP-скрипт («live_search.php») возвращает только значение «объект» и, следовательно, переменные печатают «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 script

<?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 ]

1 голос
/ 10 июля 2019

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_name & url_user. Вы не можете изменить их где-либо между ними, поэтому name & link не определены.

Кроме того, ваш 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);
0 голосов
/ 11 июля 2019
<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);

Благодаря @ Дхарману

...