It seems that your ajax (I suppose there is one because of $_POST
variables) is pretty picky regarding errors :-)
Please note that I don't know if and how you make the ajax request. So I will refer myself to an ajax request inside a script tag in a html page.
First problem:
If you are outputing with json_encode
, e.g. supposedly send data to an ajax request callback ("succes", "error", etc), then you must provide an exit();
statement right after json_encode
, in order to stop the execution of further statements. That was probably the cause of your initial error: the lack of an exit statement before mysqli_close($connect);
. Which you don't need, actually, because php closes each connection after it finishes a script processing (like getUsers.php
). Also, you don't need the ?>
tag, as @Chico3001 correctly said.
Second problem:
Your code still throws a notice, because of the if ($connect == 0)
statement:
Notice: Object of class mysqli could not be converted to int in
/getUsers.php on line 9
For proper error handling (including db connection failure) see this and this. Below I give an example too.
Third problem (depends on the 2nd one :):
A warning is raised, right after the notice.
Warning: Cannot modify header information - headers already sent by
(output started at
/getUsers.php:9) in
/getUsers.php on line
32
This is thrown because the previous notice was printed on screen - at least in my tests.
You could have seen these errors if you would have made something like this in your ajax request code:
$.ajax({
//...
error: function (jqXHR, textStatus, errorThrown) {
$('#messages').html(jqXHR.responseText);
}
});
So:
Solution 1 (recommended): Remove the if ($connect == 0)
statement and proceed with the links that I provided (regarding correct error/exception handling in PHP). See example below.
Solution 2: Replace
if ($connect == 0) {
echo "SORRY SCORE SERVER CONNECTION ERROR";
} else {}
with
if (!$connect) {
echo json_encode("SORRY SCORE SERVER CONNECTION ERROR");
exit();
}
Also, I don't think the header(...)
is necessary in your case. I am not sure because I don't know Unity.
Suggestions and code:
Please note that in my example all system-caused errors/exceptions (like db connection failure, failure in preparing/execution of the sql statements, etc) will be visible only in the log files. To be seen only by the developers, not by the users of the website. As it should be. The users should never see errors like "Sorry, connection failed". The errors which are supposed to be shown to the users (like "Please provide a user id", "No user found for the provided user id", etc) should be directly echo
-ed, or thrown & handled in "specific" try-catch blocks (like I did in getUsers.php
).
Now, because I throw and catch exceptions (as I did in getUsers.php
twice, e.g. with two try-catch blocks), the echo'ed messages will be automatically sent to the "error" function of the jquery.ajax(), not to the "success" function. You could achieve exactly the same functionality if you would use header 401 and echo
- instead of the first try-catch block, for example - like this:
if (!isset($_POST['userId']) || empty($_POST['userId'])) {
header('HTTP/1.1 401 Unauthorized');
echo 'Please provide the user ID.';
exit();
}
Or, instead of the 2nd try-catch block:
if (!$users) {
header('HTTP/1.1 404 No Content');
echo 'No users found for the provided user id.';
exit();
}
Same thing: the message would be sent to the "error" function of jquery.ajax(). The point is: any response header (see this and this) which is sent from the server to the client (e.g. browser) with a status code other than 2xx makes the ajax request to call the "error" callback - not the "success" one. In the code above the header sends a 401, or 404 code, e.g. different from 2xx (200, etc).
So, you can choose either to use try-catch blocks (like I did in getUsers.php
below), or header-echo pairs as above (also in getUsers.php
, but commented).
I tested on Apache web server + PHP 7 + MySQL 5.7 + jQuery 3.2.1 + HTML 5.
Good luck.
A code example:
index.php
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes" />
<meta charset="UTF-8" />
<!-- The above 3 meta tags must come first in the head -->
<title>Demo</title>
<script src="https://code.jquery.com/jquery-3.2.1.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
$('#submit').click(function (event) {
$('#messages').empty();
$('#results').empty();
$.ajax({
method: 'post',
dataType: 'json',
url: 'getUsers.php',
data: {
'userId': $('#userId').val()
},
success: function (response, textStatus, jqXHR) {
$.each(response, function (key, user) {
var result = 'User_Id: ' + user.User_Id + ', ';
result += 'Dia_Qty: ' + user.Dia_Qty + ', ';
result += 'Fighter_Info: ' + user.Fighter_Info + ', ';
result += 'InvBonus: ' + user.InvBonus;
$('#results').append(result);
});
},
error: function (jqXHR, textStatus, errorThrown) {
$('#messages').html(jqXHR.responseText);
},
complete: function (jqXHR, textStatus) {
//...
}
});
});
});
</script>
<style type="text/css">
body {
padding: 30px;
}
button {
padding: 5px 10px;
background-color: #8daf15;
color: #fff;
border: none;
}
#messages {
color: #c00;
margin-bottom: 15px;
}
#results {
margin-top: 20px;
}
</style>
</head>
<body>
<div id="messages">
Here come the success, or error messages...
</div>
<div class="form-container">
<label for="userId">User ID</label>
<input type="text" id="userId" name="userId" value="2">
<button type="button" id="submit" name="submit" value="submit">
Submit
</button>
</div>
<div id="results">
Here comes the fetched data...
</div>
</body>
</html>
getUsers.php:
<?php
include 'handlers.php';
include 'db.php';
// Validate the posted values.
// Like this:
try { // If an exception is thrown, then it will be handled by the "error" callback of jquery.ajax().
if (!isset($_POST['userId']) || empty($_POST['userId'])) {
throw new InvalidArgumentException('Please provide the user ID.');
}
// Here other validations...
} catch (InvalidArgumentException $exc) {
/*
* If you want you can use a header to specify a certain status code (here 401), which can be
* read in the ajax call for further customizations. I think the second parameter ("textStatus")
* of the "error" callback of jquery.ajax() is the one displaying it.
*
* Notice that no json_encode() is needed. The same applies to the error/exception handlers in
* "handlers.php". So, no json_encode() in their echo's, as well. Why? Because in the "error"
* callback the "responseText" property is used to display the error, not the "responseJSON".
*/
// header('HTTP/1.1 401 Unauthorized');
echo $exc->getMessage();
exit();
}
//**********************************************************
// ... or like this instead:
//if (!isset($_POST['userId']) || empty($_POST['userId'])) {
// header('HTTP/1.1 401 Unauthorized');
// echo 'Please provide the user ID.';
// exit();
//}
//**********************************************************
$userId = $_POST['userId'];
/*
* The SQL statement to be prepared. Notice the so-called markers,
* e.g. the "?" signs. They will be replaced later with the
* corresponding values when using mysqli_stmt::bind_param.
*
* @link http://php.net/manual/en/mysqli.prepare.php
*/
$sql = 'SELECT *
FROM Users
WHERE User_Id = ?';
/*
* Prepare the SQL statement for execution - ONLY ONCE.
*
* @link http://php.net/manual/en/mysqli.prepare.php
*/
$statement = $connection->prepare($sql);
/*
* Bind variables for the parameter markers (?) in the
* SQL statement that was passed to prepare(). The first
* argument of bind_param() is a string that contains one
* or more characters which specify the types for the
* corresponding bind variables.
*
* @link http://php.net/manual/en/mysqli-stmt.bind-param.php
*/
$statement->bind_param('i', $userId);
/*
* Execute the prepared SQL statement.
* When executed any parameter markers which exist will
* automatically be replaced with the appropriate data.
*
* @link http://php.net/manual/en/mysqli-stmt.execute.php
*/
$statement->execute();
/*
* Get the result set from the prepared statement.
*
* NOTA BENE:
* Available only with mysqlnd ("MySQL Native Driver")! If this
* is not installed, then uncomment "extension=php_mysqli_mysqlnd.dll" in
* PHP config file (php.ini) and restart web server (I assume Apache) and
* mysql service. Or use the following functions instead:
* mysqli_stmt::store_result + mysqli_stmt::bind_result + mysqli_stmt::fetch.
*
* @link http://php.net/manual/en/mysqli-stmt.get-result.php
* @link https://stackoverflow.com/questions/8321096/call-to-undefined-method-mysqli-stmtget-result
*/
$result = $statement->get_result();
/*
* Fetch data and save it into $fetchedData array.
*
* @link http://php.net/manual/en/mysqli-result.fetch-all.php
*/
// Fetch all rows at once...
$users = $result->fetch_all(MYSQLI_ASSOC);
// ... OR fetch one row at a time.
// $users = [];
// while ($row = $result->fetch_array(MYSQLI_ASSOC)) {
// $users[] = $row;
// }
/*
* Free the memory associated with the result. You should
* always free your result when it is not needed anymore.
*
* @link http://php.net/manual/en/mysqli-result.free.php
*/
$result->close();
/*
* Close the prepared statement. It also deallocates the statement handle.
* If the statement has pending or unread results, it cancels them
* so that the next query can be executed.
*
* @link http://php.net/manual/en/mysqli-stmt.close.php
*/
$statement->close();
/*
* Close the previously opened database connection.
*
* @link http://php.net/manual/en/mysqli.close.php
*/
$connection->close();
// If no users found (e.g. $users is empty) display a message.
// Like this:
try {
if (!$users) {
throw new UnexpectedValueException('No users found for the provided user id.');
}
} catch (UnexpectedValueException $exc) {
echo $exc->getMessage();
exit();
}
//****************************************************
// ... or like this instead:
//if (!$users) {
// header('HTTP/1.1 404 No Content');
// echo 'No users found for the provided user id.';
// exit();
//}
//****************************************************
echo json_encode($users);
exit();
db.php:
<?php
// Db configs.
define('HOST', 'localhost');
define('PORT', 3306);
define('DATABASE', 'tests');
define('USERNAME', 'root');
define('PASSWORD', 'root');
/*
* Enable internal report functions. This enables the exception handling,
* e.g. mysqli will not throw PHP warnings anymore, but mysqli exceptions
* (mysqli_sql_exception).
*
* MYSQLI_REPORT_ERROR: Report errors from mysqli function calls.
* MYSQLI_REPORT_STRICT: Throw a mysqli_sql_exception for errors instead of warnings.
*
* @link http://php.net/manual/en/class.mysqli-driver.php
* @link http://php.net/manual/en/mysqli-driver.report-mode.php
* @link http://php.net/manual/en/mysqli.constants.php
*/
$mysqliDriver = new mysqli_driver();
$mysqliDriver->report_mode = (MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
/*
* Create a new db connection.
*
* @see http://php.net/manual/en/mysqli.construct.php
*/
$connection = new mysqli(HOST, USERNAME, PASSWORD, DATABASE, PORT);
handlers.php:
<?php
/**
* Error handler.
*
* @link http://php.net/manual/en/function.set-error-handler.php set_error_handler.
* @param int $errno
* @param string $errstr
* @param string $errfile
* @param int $errline
*/
function errorHandler($errno, $errstr, $errfile, $errline) {
// Print a user-friendly message or show a custom error page.
echo 'An error occurred during your request. Please try again or contact us.';
// Log the error.
error_log('Error ' . $errno . ' - ' . $errstr . ' in file ' . $errfile . ' on line ' . $errline);
exit();
}
/**
* Exception handler.
*
* @link http://php.net/manual/en/function.set-exception-handler.php set_exception_handler.
* @param Exception $exception
*/
function exceptionHandler($exception) {
// Print a user-friendly message or show a custom error page.
echo 'An error occurred during your request. Please try again or contact us.';
// Log the exception.
error_log('Exception ' . $exception->getCode() . ' - ' . $exception->getMessage() . ' in file ' . $exception->getFile() . ' on line ' . $exception->getLine());
exit();
}
// Set the handlers.
set_error_handler('errorHandler');
set_exception_handler('exceptionHandler');