I am facing issues retrieving real-time user data via AJAX request from MySQL database. Currently the PHP script ("live_search.php") only returns the value "object" and hence the variables print "undefined".
I guess the issue is somewhere in the PHP script.
<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();
}
The expected result is to have a live search which returns user data in real time. In addition, I am aiming for making the row a link to the respective user (given the url_link). The load more button is secondary and not too important.
PHP does not return object. When you alert
the JSON, the variable json
is an object. Your undefined output comes from the lines:
// name holder
var name = document.createElement("span");
name.innerHTML = rowData.name;
var link = document.createElement("span");
link.innerHTML = rowData.link;
Your PHP returns an array of objects with attributes first_name
& url_user
. You do not change them anywhere in between, so name
& link
are undefined.
Additionally, your PHP is too bloated, and you can make it simpler like this for example:
<?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);