Using a prepared statement in php & mysqli - php

I am using prepared statements for the first time. And i cannot get the select to work.
For some reason, it returns all the records but i cannot get them into variables. I know it returns all the records because if i add echo '1'; to the loop it echo's 1 for each record.
Any assistance would be great. The code is below:
function builditems($quote_id){
if ($stmt = $this->link->prepare("SELECT * FROM `0_quotes_items` WHERE `quote_id` = ?")) {
// Bind a variable to the parameter as a string.
$stmt->bind_param("i", $quote_id);
// Execute the statement.
$stmt->execute();
while ($row = $stmt->fetch()) {
echo $row['id'];
}
// Close the prepared statement.
$stmt->close();
}
}
UPDATE:
in the error log, i see the following error after adding the while ($row = $stmt->fetch_assoc()) { like suggested:
PHP Fatal error: Call to undefined method mysqli_stmt::fetch_assoc()
I found a link that the same issue was had, but i do not understand how to implement the fix.
Any assistance would be great, with regards to a example.
How to remove the fatal error when fetching an assoc array

The PHP MySQLi fetch method does not access query data using brackets notation: $row['id'].
So I see two options to remedy: first find this line:
while ($row = $stmt->fetch()) {
...and modify it to, either, first add the bind_result method, and then access the data a bit differently:
$stmt->bind_result($id, $other, $whatnot); // assuming 3 columns retrieved in the query
while ($row = $stmt->fetch()) {
echo "$id $other $whatnot<br>";
}
...or, first access the result object's fetch_assoc method and use fetch_assoc instead of fetch:
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
Now you can use table column names as keys to access query data in your loop: $row['id'].
PHP MySQLi method fetch requires you to use bind_result. Doing this allows you to call your data by the variable names you've bound it to.
To use the field name as the result array index, such as: $row['id'], you need to use the PHP MySQLi fetch_assoc method. And to use fetch_assoc you need to first get the result object in order to access the fetch_assoc method.

Related

PDO fetch multiple records from database

I am writing a pretty basic piece of code to fetch one or (in most cases) multiple rows from a mysql database.
function getschema($mysqli){
$id = $_SESSION['user_id'];
$query = $mysqli->prepare("SELECT a.naam
FROM schemes AS a, aankoop AS b
WHERE b.aankoop_username_id = :userid && b.aankoop_schema_id = a.id");
$query->bind_param(':userid', $id, PDO::PARAM_INT);
$query->execute();
$result = $query->fetchAll();
echo ($result);
}
I get the user id from the session and pull the data with the query in the prepared statement.
This statement is correct. I tried it in phpmyadmin and it returns the correct values.
Now I want to use this function in my HTML like so...
<?php echo getschema($mysqli); ?>
But my code does not return a thing, it even messes up the layout of my html page where I want to show the code.
I think it probably is something with the fetchAll command. I also tried the PDO::Fetch_ASSOC but that did not work either.
In addition, I cannot see the php errors, even when they are enabled in the php.ini file.
Here's what's going on; you're mixing MySQL APIs/functions and those do not intermix.
Replace the :userid (PDO) bind in b.aankoop_username_id = :userid with a ? placeholder
b.aankoop_username_id = ?
Then this line:
$query->bind_param(':userid', $id, PDO::PARAM_INT);
Replace :userid by $id and remove , PDO::PARAM_INT but adding i
$query->bind_param("i", $id);
Sidenote: Make sure that column is int type. If not, use s instead of i.
Replace the line for fetchAll with the loop as outlined in AbraCadaver's answer.
You can't mix MySQL APIs/function, read the following on Stack:
Can I mix MySQL APIs in PHP?
Read up on mysqli with prepared statements and how it works:
http://www.php.net/manual/en/mysqli.quickstart.prepared-statements.php
Checking for errors would have outlined the errors.
http://php.net/manual/en/mysqli.error.php
http://php.net/manual/en/function.error-reporting.php
Instead of echo ($result); do return $result; in your function.
Then to use it you have to loop over the array of rows and echo the column that you want:
foreach(getschema($mysqli) as $row) {
echo $row['naam'];
}
Or assign the function return to a variable and loop over that:
$rows = getschema($mysqli);

PHP Fetchall only returning column header

I have a database that I am trying to query to get information to display to my user. I have used
fetch(PDO::FETCH_ASSOC)
before when retrieving a single row or
$row = mysql_fetch_array($result)
with good results. However, it is my understanding that it is better practice to use PDO so that is what I am trying to do.
The problem I am running into is that my results are only showing me the first row of the data I need. In this instance it is displaying the column header over and over and never giving me the data.
$stmt = $conn->prepare("SELECT ? FROM application");
$stmt->bindparam(1, $application_ID);
$stmt->execute();
$results = $stmt->fetchall(PDO::FETCH_ASSOC);
foreach($results as $row){
echo $row['application_ID'];
}
Here are the results
application_IDapplication_IDapplication_IDapplication_ID
It is good that you are aware that MySQL has been oficially deprecated and now we are supposed to used MySQLi or better yet, PDO.
Since you are not accepting any user input, there is no need of using a prepared statement.
Simply do this:
$stmt = $conn->query("SELECT * FROM application");
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach($results as $row){
echo $row['application_ID'];
//output other rows here
}
As per the php documentation pdo::fetchAll
you have to use fetchAll, instead of fetchall.

MySQLI Prepared Statement: num_rows & fetch_assoc

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';
}

bind_result into an array PHP mysqli prepared statement

wondering how i could bind the results of a PHP prepared statement into an array and then how i could go about calling them. for example this query
$q = $DBH->prepare("SELECT * FROM users WHERE username = ?");
$q->bind_param("s", $user);
$q->execute();
and this would return the results the username, email, and id. wondering if i could bind it in an array, and then store it in a variable so i could call it throughout the page?
PHP 5.3 introduced mysqli_stmt::get_result, which returns a resultset object. You can then call mysqli_result::fetch_array() or
mysqli_result::fetch_assoc(). It's only available with the native MySQL driver, though.
Rule of thumb is that when you have more than one column in the result then you should use get_result() and fetch_array() or fetch_all(). These are the functions designed to fetch the results as arrays.
The purpose of bind_result() was to bind each column separately. Each column should be bound to one variable reference. Granted it's not very useful, but it might come in handy in rare cases. Some older versions of PHP didn't even have get_result().
If you can't use get_result() and you still want to fetch multiple columns into an array, then you need to do something to dereference the values. This means giving them a new zval container. The only way I can think of doing this is to use a loop.
$data = [];
$q->bind_result($data["category_name"], $data["id"]);
while ($q->fetch()) {
$row = [];
foreach ($data as $key => $val) {
$row[$key] = $val;
}
$array[] = $row;
}
Another solution as mentioned in the comments in PHP manual is to use array_map, which internally will do the same, but in one line using an anonymous function.
while ($q->fetch()) {
$array[] = array_map(fn($a) => $a , $data);
}
Both solutions above will have the same effect as the following:
$q = $DBH->prepare("SELECT * FROM users WHERE username = ?");
$q->bind_param("s", $user);
$q->execute();
$result = $q->get_result();
$array = $result->fetch_all(MYSQLI_ASSOC);
See Call to undefined method mysqli_stmt::get_result for an example of how to use bind_result() instead of get_result() to loop through a result set and store the values from each row in a numerically-indexed array.

Why doesn't this prepare statement work in MYSQLI?

I created this code:
$statement = $db->prepare("SELECT * FROM phptech_contact");
$statement->execute();
$result = $statement->result_metadata();
$object = $result->fetch_object();
print_r( $object );
When I run it, it doesn't work. Can anybody tell me why it doesn't work?
I have 20 rows in this table so data should be returned.
From http://ch.php.net/manual/en/mysqli-stmt.result-metadata.php
Note: The result set returned by mysqli_stmt_result_metadata() contains only metadata. It does not contain any row results. The rows are obtained by using the statement handle with mysqli_stmt_fetch().
As long as you don't need this meta data you don't need to call this method.
$statement = $db->prepare("SELECT fld1, fld2 FROM phptech_contact");
$statement->execute();
$stmt->bind_result($fld1, $fld2);
while ($stmt->fetch()) {
echo "$fld1 and $fld2<br />";
}
But I really dislike the mysqli extension. PDO is much cooler ... ;-)
$db = new PDO('...');
$stmt = $db->prepare("SELECT fld1, fld2 FROM phptech_contact");
$stmt->execute();
while ($obj = $stmt->fetchObject()) {
// ...
}
or
$objs = stmt->fetchAll(PDO::FETCH_OBJ);
if you're trying to get the rows from the database, the function you need is mysqli_stmt::fetch(), not mysqli_stmt::fetch_metadata()
You're also missing a few steps. When using prepared statements, you must specify the fields you would like to return instead of using the star wildcard, and then use mysqli_stmt::bind_result() to specify which variables the database fields should be placed in.
If you're more familiar with the original MySQL extension, prepared statements have a different process to use. If your select statement has a parameter (eg., "WHERE value=?") prepared statements are definitely recommended, but for your simple query, mysqli:query() would be sufficient, and not very different from the process of mysql_query()
I believe the problem is that mysqli_stmt::result_metadata() returns a mysqli_result object without any of the actual results — it only holds metadata.
So what you want to do is use $result = $statement->bind_result(...) and then call $result->fetch() repeatedly to get the results.
One of the comments under the bind-result() article shows how to do this for a query like yours, where you don't necessarily know all of the columns being returned.

Categories