Printing an entire SQL result from a prepared statement in PHP - php

I'm trying to build a function that allows me to abstract the use of the mysqli functions in my code. Currently I have a working version for using standard SQL (no prepared statements).
function mySqlQueryToArray($con, $sql){
// Process SQL query
$result = mysqli_query($con, $sql);
if(mysqli_error($con)){
out($sql . "\n");
exit("ERROR: MySQL Error: " . mysqli_error($con));
}
// Put result into 2D array
$output = array();
while($row = mysqli_fetch_assoc($result)) {
array_push($output, $row);
}
return $output;
}
Now I'm trying to translate that code into something that can use prepared statements but my research has revealed that when using prepared statements you need to bind each column to a different variable using mysqli_stmt::bind_result which causes a problem because the point of the function is to work for an arbitrary SQL Query.
My main question is this: Is there a way to print out the entire output from a SQL query in a 2D array same as the function above does using prepared statements?
Here's my current code for using prepared statements, it has everything but the bind_result in there.
//Creates a MySQL Query, gets the result and then returns a 2D array with the results of the query
function mySqlQueryToArray($con, $sql, $params){
// Prepare SQL query
$stmt = $con->prepare($sql);
if(mysqli_error($con)){
echo "$sql=>\n" . print_r($params, true) . "\n";
exit("$sql=>\n" . print_r($params, true) . "\nERROR: MySQL Error: " . mysqli_error($con));
}
// Bind parameters
foreach($params as $param){
$type = "s";
if(gettype($param) == 'integer'){
$type = "i";
}
$stmt->bind_param($type, $param);
}
//execute query
$stmt->execute();
// Put result into 2D array
$output = array();
// ??? need to bind results and get them into an array somehow
//close prepared statement
$stmt->close();
return $output;
}

PDO turns out to be the answer. I feel like I should post the code I created to solve my problem. Thanks to #Don'tPanic for the tip.
function pdoQuery($sql, $params){
$db = new PDO('mysql:host=localhost;dbname=My_Database;charset=utf8', 'username', 'password', array(PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
try {
$stmt = $db->prepare($sql);
$stmt->execute($params);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $rows;
}catch(PDOException $ex){
echo "ERROR: SQL Error: $sql";
// logError("ERROR: SQL Error: $sql");
}
}

Related

Call to undefined method mysqli_stmt::next_result()

I'm trying to loop through a stored procedure, called via prepared statement, in PHP. Hopefully it's not impossible. Here's my PHP code:
$database = new mysqli($server, $user, $pass, $db);
$stmt = $database->prepare("CALL thisShouldReturnEightResultSets (?)");
$stmt->bind_param("i", $id);
$stmt->execute();
do {
if ($res = $stmt->bind_result($myvar)) {
$stmt->fetch();
echo "*" . $myvar . "<br/>";
} else {
if ($stmt->errno) {
echo "Store failed: (" . $stmt->errno . ") " . $stmt->error;
}
}
} while ($stmt->next_result());
That should print like so:
* 4
* 16
* 7
etc...
... and then exit once it runs of out result sets. Instead I get:
* 4
Fatal error: Call to undefined method mysqli_stmt::next_result()
At first I tried get_result instead of bind_result, but that errored. Based on this I found that I don't have the mysqlnd driver installed. Iworked around that with bind_result. Now I need a work around for next_result which I'm guessing is part of the mysqlnd driver as well. What are my options here? Tech notes:
PHP Version 5.3.2-1ubuntu4.11
Thanks.
I don't think you can do this with a prepared statement, since you don't have the MYSQLND driver. You'll have to do it the old fashioned way, with escaping.
$id = $database->real_escape_string($id);
if ($database->multi_query("CALL thisShouldReturnEightResultSets ('$id')")) {
do {
if ($result = $database->store_result()) {
while ($row = $result->fetch_row()) {
echo "*" . $row[0] . "<br/>";
}
}
} while ($database->next_result());
}
bindResult does not like multiple results.
Use get_result() then fetch_assoc and store in an array,
Then use a foreach loop to output your results.
$res = $stmt->get_result();
$array[];
while($x = $res->fetch_assoc()){
$array[]=$x;
}

Prepared Statement Return Get Results & Count

I am trying to get both the results of my query and the row count wihtout having to make two trips the the DB if possible. I am using prepared statements in a procedural way. My code is as follows:
$dbd = mysqli_stmt_init($dbconnection);
if (mysqli_stmt_prepare($dbd, "SELECT * FROM Contacts WHERE First_Name = ?" )) {
mysqli_stmt_bind_param($dbd, "s", $val1);
if (!mysqli_stmt_execute($dbd)) {
echo "Execute Error: " . mysqli_error($dbconnection);
} else {
//do nothing
}
} else {
echo "Prep Error: " . mysqli_error($dbconnection);
}
$result = mysqli_stmt_get_result($dbd);
So the above code works just fine and returns my results. What I want to do now is get the row count using this same statement but i don't want to have to write a brand new prepared statement. If I writer a separate prepared statement and use store_results and num_rows I get the row count but that would force me to have to write an entire new block of code and trip to db. I am trying to do something as follows but It throws and error:
$dbd = mysqli_stmt_init($dbconnection);
if (mysqli_stmt_prepare($dbd, "SELECT * FROM Contacts WHERE First_Name = ?" )) {
mysqli_stmt_bind_param($dbd, "s", $val1);
if (!mysqli_stmt_execute($dbd)) {
echo "Execute Error: " . mysqli_error($dbconnection);
} else {
//do nothing
}
} else {
echo "Prep Error: " . mysqli_error($dbconnection);
}
$result = mysqli_stmt_get_result($dbd);
mysqli_stmt_store_result($dbd);
$rows = mysqli_stmt_num_rows($dbd);
The throws and error as if i can't run both get results and store results using the same prepared statement. Im simply trying to keep my code compact and reuse as much as possible. If i break the above out into two separat prepared statements it works fine, Im just wondering there is a way to just add a line or two to my existing statement and get the row count. Or do i have to write an entire new block of code with new stmt_init, stmt_prepare, bind_param, execute, etc...
I tried your code (and reformatted it a bit), but I can't get it to work when I use both store_result() and get_result(). I can only use store_result then bind_result().
So the alternative is to fetch all the rows and then count them:
Example:
$sql = "SELECT * FROM Contacts WHERE First_Name = ?";
$stmt = mysqli_stmt_init($dbconnection);
if (mysqli_stmt_prepare($stmt, $sql) === false) {
trigger_error("Prep Error: " . mysqli_error($dbconnection));
return 1;
}
if (mysqli_stmt_bind_param($stmt, "s", $val1) === false) {
trigger_error("Bind Error: " . mysqli_stmt_error($stmt));
return 1;
}
if (mysqli_stmt_execute($stmt) === false) {
trigger_error("Execute Error: " . mysqli_stmt_error($stmt));
return 1;
}
$result = mysqli_stmt_get_result($stmt);
$rows = mysqli_fetch_all($result, MYSQLI_ASSOC);
$num_rows = count($rows);
print "$num_rows rows\n";
foreach ($rows as $row) {
print_r($row);
}
In my opinion, PDO is much easier:
$pdo = new PDO("mysql:host=127.0.0.1;dbname=test", "xxxx", "xxxxxxxx");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$sql = "SELECT * FROM Contacts WHERE First_Name = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$val1]);
$num_rows = $stmt->rowCount();
print "$num_rows rows\n";
while ($row = $stmt->fetch()) {
print_r($row);
}

PHP MySQLi bind param for array

I'm having problems with a PHP script that returns some info based on a supplied array of identifiers (MAC addresses).
It gives me a 500 unspecified error.
if (!isset($_POST['macs'])) {
echo 'Please enter mac addresses!';
die;
}
$mysqli = new mysqli("x", "x", "x", "x");
/* check connection */
if ($mysqli->connect_error)
die("$mysqli->connect_errno: $mysqli->connect_error");
$stmt = $mysqli->stmt_init();
/* create a prepared statement */
$query = "SELECT username, mac FROM user WHERE mac IN (" . str_repeat("?,", count($_POST['macs']));
$query = rtrim($query, ",");
$query = $query . ')';
if ($mysqli->prepare($query)) {
call_user_func_array(array($stmt, "bind_param"), array_merge(array('s'), $_POST['macs']));
/* execute query */
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
echo $row['username'];
}
/* close statement */
mysqli_stmt_close($stmt);
}
mysqli_close($link);
This is what I'm posting via the Postman Chrome app:
macs[0] = 'F0:72:8C:F3:B5:66'
macs[1] = 'FA:72:8C:F3:B5:66'
Can anyone at least hint me at what's causing the problem. I'm guessing it's the call_user_func_array call but, I'm unsure of what's the actual problem.
// If you bind array-elements to a prepared statement, the array has to be declared first with the used keys:
Coming to the problem calling mysqli::bind_param() with a dynamic number of arguments via call_user_func_array() with PHP Version 5.3+, there's another workaround besides using an extra function to build the references for the array-elements.
You can use Reflection to call mysqli::bind_param().
Example:
<?php
$db = new mysqli("localhost","root","","tests");
$res = $db->prepare("INSERT INTO test SET foo=?,bar=?");
$refArr = array("si","hello",42);
$ref = new ReflectionClass('mysqli_stmt');
$method = $ref->getMethod("bind_param");
$method->invokeArgs($res,$refArr);
$res->execute();
for more
http://php.net/manual/en/mysqli-stmt.bind-param.php#104073

two mysqli querys, one in a while loop

Can't seam to find the answer to this.
I have a mysqli loop statement. And in that loop I want to run another query. I cant write these two sql together. Is that possible?
I thought since I use stmt and set that to prepare statement. So i add another variable stmt2. Running them seperate works, but run it like I wrote it gives me "mysqli Fatal error: Call to a member function bind_param() on a non-object"
Pseudocode :
loop_sql_Statement {
loop_another_sql_statement(variable_from_firsT_select) {
echo "$first_statement_variables $second_statemenet_variables";
}
}
$sql = "select dyr_id, dyr_navn, type_navn, dyr_rase_id, dyr_fodt_aar, dyr_kommentar, dyr_opprettet, dyr_endret
from dyr_opphald, dyr, dyr_typer
where dyropphald_dyr_id = dyr_id
and dyr_type_id = type_id
and dyropphald_opphald_id = ?";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param("i",
$p_opphald_id);
$stmt->execute();
$stmt->bind_result($dyr_id, $dyr_navn, $type_navn, $dyr_rase_id, $dyr_fodt_aar, $dyr_kommentar, $dyr_opprettet, $dyr_endret);
echo "<table>";
while($stmt->fetch()) {
echo "<tr><td>$dyr_navn</td><td>$type_navn</td><td>$dyr_rase_id</td><td>$dyr_fodt_aar</td><td>";
$sql2 = "select ekstra_ledetekst, ekstradyr_ekstra_verdi from dyr_ekstrainfo, ekstrainfo where ekstradyr_ekstra_id = ekstra_id and ekstradyr_dyr_id = ?";
try {
$stmt2 = $mysqli->prepare($sql2);
$stmt2->bind_param("i",
$dyr_id);
$stmt2->execute();
$stmt2->bind_result($ekstra_ledetekst, $ekstra_ledetekst);
echo "<td>";
while($stmt2->fetch()) {
echo "$ekstra_ledetekst => $ekstra_ledetekst<br>";
}
}catch (Exception $e) {}
echo "</td></tr>";
}
echo "</table>";
The answer:
Silly me, I didnt know I had to have two mysqli connection. So the solution was to declare another mysqli connection.
$mysqli = new mysqli($start, $name, $pwd, $selected_db);
$mysqli2 = new mysqli($start, $name, $pwd, $selected_db);
You should be able to do that, although you make have to start a second connection.

How does one output data using mySQL PDO?

New to mySQL PDO. I have read other answers here and read tutorials and am finally taking the plunge. Problem is I cannot seem to output data. Hence, can someone assess my code to ensure it is correct? Also, is the system I am using to query the db efficient and clean and secure? thanks
$pdo --- the correct connection information is in this line but has been removed ---
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// SELECT sql query
try {
$thedate='2013-06-03';
$rotation=1;
$stmt = $pdo->prepare("SELECT * FROM sched_main_2013 WHERE thedate=:thedate AND rotation=:rotation");
$stmt->bindValue(':thedate', $thedate, PDO::PARAM_STR);
$stmt->bindValue(':rotation', $rotation, PDO::PARAM_INT);
$stmt->execute();
$stmt->setFetchMode(PDO::FETCH_ASSOC);
}
catch(PDOException $ex) {
echo $ex->getMessage();
}
while($rows = $stmt->fetch()) {
echo $rows['thedate'] . "\n";
echo $rows[assignedRad] . "\n";
echo $rows[rotation] . "\n";
}
// close the connection
$pdo = null;
This code outputs nothing. No errors. Nothing at all.
By the way, the table exists and the SELECT * FROM works fine when I manually run the mySQL statement, so data does exist with this query.
Try
while($rows = $stmt->fetch()) {
echo $rows['thedate'] . "\n";
echo $rows[assignedRad] . "\n";
echo $rows[rotation] . "\n";
}
To
while($rows = $stmt->fetch()) {
echo $rows['thedate'] . "\n";
echo $rows['assignedRad'] . "\n";
echo $rows['rotation'] . "\n";
}
Debug 01
Maybe you can try this to test whether you truly receive any data from database
print_r($stmt->fetchAll());
Instead of your while-loop
Debug 02
Try the simple query that you strongly believe there will be no SQL error for example:
SELECT * FROM sched_main_2013
Without any value binding.
Debug 03
Try another query with WHERE condition, but no binding
SELECT * FROM sched_main_2013 WHERE thedate='2013-06-03' AND rotation=1
You told that var_dump($row) gives you FALSE. The documentation says:
The return value of this function on success depends on the fetch type. In all cases, >FALSE is returned on failure.
Add the following line:
while($row = $stmt->fetch()) {
echo $row['thedate'] . "\n";
echo $row['assignedRad'] . "\n";
echo $row['rotation'] . "\n";
}
if($row === FALSE) {
var_dump($stmt->errorInfo());
die();
}
Further note: You originally named the return value of $stmt->fetch() $rows (plural) instead of $row. I'm not sure whether you know that the method will return a single row each time it is called.
What it have to be
$sql = "SELECT * FROM sched_main_2013 WHERE thedate=? AND rotation=?";
$data = array('2013-06-03', 1);
$stmt = $pdo->prepare($sql);
$stmt->execute($data);
$rows = $stmt->fetchAll();
var_dump($rows);
$sql = "SELECT * FROM sched_main_2013";
$data = array();
$stmt = $pdo->prepare($sql);
$stmt->execute(array());
$rows = $stmt->fetchAll();
var_dump($rows);
If second query returns the rows while first doesn't - there is no data found.
If both returns no rows - then it is caused by bad database design which is clearly seen from the table name, which should never have a postfix like this

Categories