Here's my code
$stmt = $conn->mysqli->stmt_init();
$stmt = $conn->mysqli->prepare('SELECT Username, EmailVerified, Blocked FROM user WHERE Email = ? AND SLANumber = ? AND Password = ?');
$stmt->bind_param('ssb', $_POST['EmailID'], $_POST['SLANumber'], $_POST['Password']);
$stmt->execute();
$stmt->store_result();
$result = $stmt->get_result();
if($result->num_rows == 0){
echo 'No rows found';
}
else{
// Continue processing here
.....
}
The code always echoes No rows found. A day or two before, it was working fine.
As expected, running the query directly gives the desired result.
What's wrong with the code?
Don't use store_result and get_result together in the same statement.
Use store_result method with "num_rows", "bind_result" and "fetch".
For get_result method, use "affected_rows" and "fetch_array". You can still use the "num_rows" property in the income get_result method as shown below.
$stmt->execute();
// $stmt->store_result();
$result = $stmt->get_result();
if(result->num_rows == 0){
...
}
OR
$stmt->execute();
// $stmt->store_result();
$result = $stmt->get_result();
if($stmt->affected_rows == 0){
...
}
To fix your problem remove this line:
$stmt->store_result();
The problem is that you used two methods which are in conflict with each other.
$stmt->store_result();
$result = $stmt->get_result();
Both of these methods fetch the results. store_result() fetches the results internally and stores them in the statement object. I would advise to avoid this method whenever possible. It is difficult to use. get_result() fetches the results and saves them in a separate object. Once the results are fetched from MySQL, they cannot be fetched again. Use only one of these methods at a time.
In your case you first stored the results in mysqli_stmt and then fetched an empty result set into $result. $result will contain 0 rows, because all of the records have already been stored in the statement. To get the number of rows stored there use $stmt->num_rows.
Both mysqli_stmt and mysqli_result classes have the num_rows property. The key is to use the appropriate one.
num_rows is a property of mysqli_stmt, not of a result resource. So you should be doing:
$result = $stmt->get_result();
// Also check strict comparison against int 0,
// to avoid incorrect equality with boolean FALSE
if($stmt->num_rows === 0){
echo 'No rows found';
}
Related
What are the differences and specific use cases of these two functions? Here's what I found:
mysqli_free_result — Frees the memory associated with a result
mysqli_stmt_free_result — Frees stored result memory for the given statement handle
An example will be nice.
These are two different functions, but you don't need to use any of them.
mysqli_free_result
mysqli_free_result() is the procedural equivalent of $result->free(). All it does is it unsets the results from the variable. The object still exists, but becomes unusable.
$id = 1;
$stmt = $mysqli->prepare('SELECT * FROM student_detail WHERE ID=?');
$stmt->bind_param('s', $id);
$stmt->execute();
$result = $stmt->get_result();
$result->free();
var_dump($result->fetch_assoc()); // error
It also has 2 aliases. These 4 are all the same thing:
$result->free();
$result->close();
$result->free_result();
mysqli_free_result($result);
mysqli_stmt_free_result
Does the same thing, but with the statement itself. It is the equivalent of $stmt->free_result()
$id = 1;
$stmt = $mysqli->prepare('SELECT * FROM student_detail WHERE ID=?');
$stmt->bind_param('s', $id);
$stmt->execute();
$result = $stmt->store_result();
$stmt->free_result();
var_dump($stmt->fetch()); // false
You can assume that if you ever find yourself needing to use any of them, then it means you have probably done something wrong.
For example, some people claim it saves memory for your server when you free the result once you are done with it. In reality you should encapsulate your database queries in such way that the mysqli_result lives only as long as you need it. Take a look at one method I have written a while ago:
public function safeQuery(string $sql, array $params = []): ?array {
$stmt = $this->prepare($sql);
if ($params) {
$stmt->bind_param(str_repeat("s", count($params)), ...$params);
}
$stmt->execute();
if ($result = $stmt->get_result()) {
return $result->fetch_all(MYSQLI_BOTH);
}
return null;
}
It executes prepared statement, gets the result, fetches the records and the mysqli_result is alive as long as it is needed and not a moment more.
They're equivalent, it depends on how you created the results in the first place.
If you use a prepared statement and then use $stmt->store_result(), you would free the results using $stmt->free_result().
If you perform an ordinary query like $result = $conn->query(...), you would free it using $result->free_result().
I have this code.
$stmt = $conn->prepare("SELECT * FROM UserData WHERE username = ?");
$stmt->bind_param('s',$username);
//$username = $_POST["username"];
$username ="netsgets";
$stmt->execute();
$stmt->store_result();
var_dump(stmt['likedFour']);
According to table UserData, likeFour should equal 'empty'. For some reason, var_dump(stmt['likedFour']); is returning the string 's'. Why is this?
Edit (this is what you told me to do but it is not working):
when I run this the script stops at the var_dump.
require "conn.php";
echo "debug 1";
$stmt = $conn->prepare("SELECT * FROM UserData WHERE username = ?");
$stmt->bind_param('s',$username);
//$username = $_POST["username"];
$username ="netsgets";
$stmt->execute();
$row = $stmt->fetch_assoc();
var_dump($row['likedFour']);
Why does var_dump(stmt['likedFour']); return 's':
Because you're missing the dollar sign before stmt, so PHP thinks you're trying to access the constant stmt instead of the variable $stmt. Since you haven't defined that constant, it will fall back to assuming you're trying to access the string "stmt". For strings, indices must be numeric so PHP should be throwing you an "Illegal string offset" warning but will try to fix it for you by casting 'likedFour' to an integer (which will be 0).
Therefore, var_dump(stmt['likedFour']) means the exact same thing as var_dump("stmt"[0]) to PHP, which is why you're getting the output "s": the first character from "stmt".
How to get the result you actually want:
You first need to retrieve the resulting rows from your query. $stmt is the mysqli_stmt object that you use to execute the query and retrieve the results, it is not actually the result itself.
To save yourself headaches in the future, always check whether your query even executed successfully before trying to retrieve the results. Then fetch the row of data:
$success = $stmt->execute();
if (!$success) {
echo $stmt->error;
} else if ($stmt->num_rows == 0) {
echo 'No results matching that username';
} else {
$result = $stmt->get_result();
$row = $result->fetch_assoc();
var_dump($row['likedFour']);
}
If you don't know how many rows will be returned, loop through them just to be safe:
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
var_dump($row['likedFour']);
}
I have this code.
$stmt = $conn->prepare("SELECT * FROM UserData WHERE username = ?");
$stmt->bind_param('s',$username);
//$username = $_POST["username"];
$username ="netsgets";
$stmt->execute();
$stmt->store_result();
var_dump(stmt['likedFour']);
According to table UserData, likeFour should equal 'empty'. For some reason, var_dump(stmt['likedFour']); is returning the string 's'. Why is this?
Edit (this is what you told me to do but it is not working):
when I run this the script stops at the var_dump.
require "conn.php";
echo "debug 1";
$stmt = $conn->prepare("SELECT * FROM UserData WHERE username = ?");
$stmt->bind_param('s',$username);
//$username = $_POST["username"];
$username ="netsgets";
$stmt->execute();
$row = $stmt->fetch_assoc();
var_dump($row['likedFour']);
Why does var_dump(stmt['likedFour']); return 's':
Because you're missing the dollar sign before stmt, so PHP thinks you're trying to access the constant stmt instead of the variable $stmt. Since you haven't defined that constant, it will fall back to assuming you're trying to access the string "stmt". For strings, indices must be numeric so PHP should be throwing you an "Illegal string offset" warning but will try to fix it for you by casting 'likedFour' to an integer (which will be 0).
Therefore, var_dump(stmt['likedFour']) means the exact same thing as var_dump("stmt"[0]) to PHP, which is why you're getting the output "s": the first character from "stmt".
How to get the result you actually want:
You first need to retrieve the resulting rows from your query. $stmt is the mysqli_stmt object that you use to execute the query and retrieve the results, it is not actually the result itself.
To save yourself headaches in the future, always check whether your query even executed successfully before trying to retrieve the results. Then fetch the row of data:
$success = $stmt->execute();
if (!$success) {
echo $stmt->error;
} else if ($stmt->num_rows == 0) {
echo 'No results matching that username';
} else {
$result = $stmt->get_result();
$row = $result->fetch_assoc();
var_dump($row['likedFour']);
}
If you don't know how many rows will be returned, loop through them just to be safe:
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
var_dump($row['likedFour']);
}
The following code returns 0, even though there are 5 entries in the table categories with cat = 1.
$sql = "SELECT name FROM categories WHERE cat = ?";
$stmt = $db->prepare($sql);
$cat = 1;
$stmt->bind_param("i", $cat);
$stmt->execute();
$stmt->get_result();
echo $stmt->num_rows;
However, when I change $stmt->get_result(); to $stmt->store_result(); the output is 5. Why does get_result() not work here?
I found for instance on this answer: https://stackoverflow.com/a/8722329/2311074 that get_result() should also work.
Looks like the other answer is wrong and get_result doesn't change the state of a statement (which is quite logical, as you are asking for mysqli_result and therefore supposedly going to work with it from now on).
You see, the way you are using get_result is quite pointless. To make any point of it, you have to assign the result to a variable, which will give you the desired outcome:
$res = $stmt->get_result();
echo $res->num_rows;
Note that the num_rows property is quite useless in general. If you want to know whether your query returned any data or not, just collect the rows into array and then you use this array for the purpose.
$data = $stmt->get_result()->fetch_all();
if ($data) {
// whatever
} else {
// oops!
}
And of course you shouldn't use such a query only to count the goods available in a category. For such a purpose a count(*) query have to be used.
Below is some poorly written and heavily misunderstood PHP code with no error checking. To be honest, I'm struggling a little getting my head around the maze of PHP->MySQLi functions! Could someone please provide an example of how one would use prepared statements to collect results in an associative array whilst also getting a row count from $stmt? The code below is what I'm playing around with. I think the bit that's throwing me off is using $stmt values after store_result and then trying to collect an assoc array, and I'm not too sure why...
$mysqli = mysqli_connect($config['host'], $config['user'], $config['pass'], $config['db']);
$stmt = $mysqli->prepare("SELECT * FROM licences WHERE generated = ?");
$stmt->bind_param('i', $core['id']);
$result = $stmt->execute();
$stmt->store_result();
if ($stmt->num_rows >= "1") {
while($data = $result->fetch_assoc()){
//Loop through results here $data[]
}
}else{
echo "0 records found";
}
I feel a little cheeky just asking for code, but its a working demonstration of my circumstances that I feel I need to finally understand what's actually going on. Thanks a million!
I searched for a long time but never found documentation needed to respond correctly, but I did my research.
$stmt->get_result() replace $stmt->store_result() for this purpose.
So, If we see
$stmt_result = $stmt->get_result();
var_dump($stmt_result);
we get
object(mysqli_result)[3]
public 'current_field' => int 0
public 'field_count' => int 10
public 'lengths' => null
public 'num_rows' => int 8 #That we need!
public 'type' => int 0
Therefore I propose the following generic solution. (I include the bug report I use)
#Prepare stmt or reports errors
($stmt = $mysqli->prepare($query)) or trigger_error($mysqli->error, E_USER_ERROR);
#Execute stmt or reports errors
$stmt->execute() or trigger_error($stmt->error, E_USER_ERROR);
#Save data or reports errors
($stmt_result = $stmt->get_result()) or trigger_error($stmt->error, E_USER_ERROR);
#Check if are rows in query
if ($stmt_result->num_rows>0) {
# Save in $row_data[] all columns of query
while($row_data = $stmt_result->fetch_assoc()) {
# Action to do
echo $row_data['my_db_column_name_or_ALIAS'];
}
} else {
# No data actions
echo 'No data here :(';
}
$stmt->close();
$result = $stmt->execute(); /* function returns a bool value */
reference : http://php.net/manual/en/mysqli-stmt.execute.php
so its just sufficient to write $stmt->execute(); for the query execution.
The basic idea is to follow the following sequence :
1. make a connection. (now while using sqli or PDO method you make connection and connect with database in a single step)
2. prepare the query template
3. bind the the parameters with the variable
4. (set the values for the variable if not set or if you wish to change the values) and then Execute your query.
5. Now fetch your data and do your work.
6. Close the connection.
/*STEP 1*/
$mysqli = mysqli_connect($servername,$usrname,$pswd,$dbname);
/*STEP 2*/
$stmt = $mysqli->prepare("SELECT * FROM licences WHERE generated = ?");
/*Prepares the SQL query, and returns a statement handle to be used for further operations on the statement.*/
//mysqli_prepare() returns a statement object(of class mysqli_stmt) or FALSE if an error occurred.
/* STEP 3*/
$stmt->bind_param('i', $core['id']);//Binds variables to a prepared statement as parameters
/* STEP 4*/
$result = $stmt->execute();//Executes a prepared Query
/* IF you wish to count the no. of rows only then you will require the following 2 lines */
$stmt->store_result();//Transfers a result set from a prepared statement
$count=$stmt->num_rows;
/*STEP 5*/
//The best way is to bind result, its easy and sleek
while($data = $stmt->fetch()) //use fetch() fetch_assoc() is not a member of mysqli_stmt class
{ //DO what you wish
//$data is an array, one can access the contents like $data['attributeName']
}
One must call mysqli_stmt_store_result() for (SELECT, SHOW, DESCRIBE, EXPLAIN), if one wants to buffer the complete result set by the client, so that the subsequent mysqli_stmt_fetch() call returns buffered data.
It is unnecessary to call mysqli_stmt_store_result() for other queries, but if you do, it will not harm or cause any notable performance in all cases.
--reference: php.net/manual/en/mysqli-stmt.store-result.php
and http://www.w3schools.com/php/php_mysql_prepared_statements.asp
One must look up the above reference who are facing issue regarding this,
My answer may not be perfect, people are welcome to improve my answer...
If you would like to collect mysqli results into an associative array in PHP you can use fetch_all() method. Of course before you try to fetch the rows, you need to get the result with get_result(). execute() does not return any useful values.
For example:
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli($config['host'], $config['user'], $config['pass'], $config['db']);
$mysqli->set_charset('utf8mb4'); // Don't forget to set the charset!
$stmt = $mysqli->prepare("SELECT * FROM licences WHERE generated = ?");
$stmt->bind_param('i', $core['id']);
$stmt->execute(); // This doesn't return any useful value
$result = $stmt->get_result();
$data = $result->fetch_all(MYSQLI_ASSOC);
if ($data) {
foreach ($data as $row) {
//Loop through results here
}
} else {
echo "0 records found";
}
I am not sure why would you need num_rows, you can always use the array itself to check if there are any rows. An empty array is false-ish in PHP.
Your problem here is that to do a fetch->assoc(), you need to get first a result set from a prepared statement using:
http://php.net/manual/en/mysqli-stmt.get-result.php
And guess what: this function only works if you are using MySQL native driver, or "mysqlnd". If you are not using it, you'll get the "Fatal error" message.
You can try this using the mysqli_stmt function get_result() which you can use to fetch an associated array. Note get_result returns an object of type mysqli_result.
$stmt->execute();
$result = $stmt->get_result(); //$result is of type mysqli_result
$num_rows = $result->num_rows; //count number of rows in the result
// the '=' in the if statement is intentional, it will return true on success or false if it fails.
if ($result_array = $result->fetch_assoc(MYSQLI_ASSOC)) {
//loop through the result_array fetching rows.
// $ rows is an array populated with all the rows with an associative array with column names as the key
for($j=0;$j<$num_rows;$j++)
$rows[$j]=$result->fetch_row();
var_dump($rows);
}
else{
echo 'Failed to retrieve rows';
}