I'm trying to simplify a repetitive script that I'm doing in PHP. I've looked at a few loop options but since it involves rowsets being returned from a MySQL stored procedure it's not acting properly. I'm doing this same script about 15 times to return all the data. Ultimately I'm looking to pass back a json_encode array to the ajax calling it. The results I keep getting when trying to put it in a loop is a 500 error or a poorly constructed array.
$stmt->execute();
$values = array();
$stmt->execute();
$values = array();
$rowCount = $stmt->rowCount();
if ($rowCount > 0) {
$row = $stmt->fetchAll(PDO::FETCH_NUM);
$values = array();
foreach ($row as $rowvalue) {
$values[] = array($rowvalue[0], $rowvalue[1], $rowvalue[2], $rowvalue[3], $rowvalue[4], $rowvalue[5]);
}
$stmt -> nextRowset();
$row = $stmt->fetchAll();
foreach ($row as $rowvalue) {
$values[] = array($rowvalue[0], $rowvalue[1], $rowvalue[2], $rowvalue[3], $rowvalue[4], $rowvalue[5]);
}
$stmt -> nextRowset();
$row = $stmt->fetchAll();
foreach ($row as $rowvalue) {
$values[] = array($rowvalue[0], $rowvalue[1], $rowvalue[2], $rowvalue[3], $rowvalue[4], $rowvalue[5]);
}
...
echo json_encode($values);
}
Updated to use the code example below:
$sql = 'CALL fo_SELECT_Operations_Detail(?,?,?)';
$facility = $_POST['facility'];
$startweek = $_POST['startweek'];
$endweek = $_POST['endweek'];
$sql->bindParam(1, $facility, PDO::PARAM_STR);
$sql->bindParam(2, $startweek, PDO::PARAM_STR);
$sql->bindParam(3, $endweek, PDO::PARAM_STR);
$stmt = $conn->query($sql);
$values = array();
do {
$rows = $stmt->fetchAll(PDO::FETCH_NUM);
foreach ($rows as $r) {
$values[] = array($r[0], $r[1], $r[2], $r[3], $r[4], $r[5]);
}
} while ($stmt->nextRowset());
// all processed so now send JSON
echo json_encode($values);
We all forget that SP's which create rowsets also create an annoying empty one as well that has to be Next'd over, but not actually unloaded. The && $stmt->columnCount() looks after getting nextRowset() called but not actually attempting to process it in any way.
$sql = 'CALL fo_SELECT_Operations_Detail(?,?,?)';
$stmt->prepare($sql);
$stmt->bindParam(1, $_POST['facility'], PDO::PARAM_STR);
$stmt->bindParam(2, $_POST['startweek'], PDO::PARAM_STR);
$stmt->bindParam(3, $_POST['endweek'], PDO::PARAM_STR);
$stmt = $conn->execute();
$values = array();
do {
$rows = $stmt->fetchAll(PDO::FETCH_NUM);
foreach ($rows as $r) {
$values[] = [$r[0], $r[1], $r[2], $r[3], $r[4], $r[5]];
}
} while ($stmt->nextRowset() && $stmt->columnCount());
// all processed so now send JSON
echo json_encode($values);
Related
I have the following php code:
$user_id = $user["id_user_key"];
$stmt = $db->prepare("CALL spGetUserProducts(?)");
$stmt->bind_param('i', $user_id);
$stmt->execute();
$result = $stmt->get_result();
$data = array();
while($row = $result->fetch_assoc()) {
$row_array = array();
$row_array["id"] = $row["id"];
$row_array["pname"] = $row["pname"];
$row_array["picon"] = $row["picon"];
$row_array["menuItems"] = array();
$product = $row["id"];
//loop
$result_opt = $db->query("CALL spGetUserProductViews($user_id, $product)");
while ($opt_fet = $result_opt->fetch_assoc()) {
$row_array["menuItems"][] = array(
"id" => $opt_fet["id"],
"vname" => $opt_fet["vname"],
"isheader" => $opt_fet["isheader"]
);
}
array_push($data, $row_array);
}
$stmt->close();
echo json_encode($data);
The first loop can get a hold of $db, in other words: the first prepared statement is being excecuted and gives me results. The second one:
$result_opt = $db->query("CALL spGetUserProductViews($user_id, $product)");
gives me false. When I try this statement outside the loop, it does work.
Any thoughts ont his?
I found out that mysqli can't handle two simultaneous queries because mysqli uses unbuffered queries by default. Now, I could have dived into this (for example make use of $stmt->store-result()), but I also realized that I would like to keep the load on my database to a minimum.
My solution:
$data = array();
$user_id = $user["id_user_key"];
//menus -> products
$stmt = $db->prepare("CALL spGetUserProducts(?)");
$stmt->bind_param("i", $user_id);
$stmt->execute();
$result = $stmt->get_result();
$menus = array();
while($row = $result->fetch_assoc()) {
$menus[] = $row;
}
$stmt->close();
//items -> views
$stmt = $db->prepare("CALL spGetUserProductViews(?)");
$stmt->bind_param("i", $user_id);
$stmt->execute();
$result = $stmt->get_result();
$items = array();
while($row = $result->fetch_assoc()) {
$items[] = $row;
}
$stmt->close();
//generate object
//loop menus
foreach($menus as $m){
$row_array = array();
$row_array["id"] = $m["id"];
$row_array["pname"] = $m["pname"];
$row_array["picon"] = $m["picon"];
$row_array["menuItems"] = array();
//loop items
foreach($items as $i) {
if($m["id"] == $i["id_product"]) {
$row_array["menuItems"][] = array(
"id" => $i["id"],
"vname" => $i["vname"],
"isheader" => $i["isheader"]
);
}
}
array_push($data, $row_array);
}
echo json_encode($data);
So now I first generate arrays out of the two objects. then I do a foreach over the menus and then over the items. When the $menu["id"] equals $items["id_product"] then the array with items for that specific menu is being generated.
EDIT
After the data has been pulled from the database I first have to do a check wether or not the array contains data:
if(!empty($menus) && !empty($items)) {
foreach ($menus as $m) {
$row_array = array();
$row_array["id"] = $m["id"];
$row_array["pname"] = $m["pname"];
$row_array["picon"] = $m["picon"];
$row_array["menuItems"] = array();
//loop items
foreach ($items as $i) {
if ($m["id"] == $i["id_product"]) {
$row_array["menuItems"][] = array(
"id" => $i["id"],
"vname" => $i["vname"],
"isheader" => $i["isheader"]
);
}
}
array_push($data, $row_array);
}
}
I am changing mysqli connections to prepared statements, I always come across this issue, when I am putting values in an array, I'm wondering if someone could explain why I do this incorrectly every time. When I print the returned array from the function it only shows me the last stored values in the array, as opposed to every row in the array.
function getResults($db) {
$statement = $db->prepare("SELECT inv_id, serial_num, equip_id, equip_title, equip_cat, input_date, date_modified FROM equip_inv");
$statement->execute();
$statement->store_result();
$num_of_rows = $statement->num_rows;
$statement->bind_result($invId, $serial, $equipId, $equipTitle, $equipCat, $inputDate, $dateMod);
while ($statement->fetch()) {
$resultArray = array();
$resultArray['inv_id'] = $invId;
$resultArray['serial_num'] = $serial;
$resultArray['equip_id'] = $equipId;
$resultArray['equip_title'] = $equipTitle;
$resultArray['equip_cat'] = $equipCat;
$resultArray['input_date'] = $inputDate;
$resultArray['date_modified'] = $dateMod;
}
return $resultArray;
}
You're reseting $resultArray in each loop. You can create a new array $results = array(); and push $resultArray to it in each loop. Try :
function getResults($db){
$statement = $db->prepare("SELECT inv_id, serial_num, equip_id, equip_title, equip_cat, input_date, date_modified FROM equip_inv");
$statement->execute();
$statement->store_result();
$num_of_rows = $statement->num_rows;
$statement->bind_result($invId, $serial, $equipId, $equipTitle, $equipCat, $inputDate, $dateMod);
$results = array();
while ($statement->fetch()){
$resultArray = array();
$resultArray['inv_id'] = $invId;
$resultArray['serial_num'] = $serial;
$resultArray['equip_id'] = $equipId;
$resultArray['equip_title'] = $equipTitle;
$resultArray['equip_cat'] = $equipCat;
$resultArray['input_date'] = $inputDate;
$resultArray['date_modified'] = $dateMod;
$results[] = $resultArray;
}
return $results;
}
I have an array of strings called $lines and I want to search a database with each string.
What I have that works:
foreach($lines as $line) {
$line = real_escape_string($line);
$sql = "select * from $table where $column like '%$line%'"
$result = $conn->query($sql);
if($result->num_rows) {
while ($row = $result->fetch_assoc())
//Name and Date are are only 2 out of 15+ column names from the db table
echo "<tr><td> {$row['Name']} </td>
<td> {$row['Date']} </td></tr>";
}
However, I don't want this. I want to use prepared statements and be able to use column names like above. What I've tried: (from here)
$vars = array();
$data = array();
$stmt = $conn->prepare("SELECT * FROM $table WHERE `$column` LIKE '%?%'");
$stmt->bind_param("s", $line);
$stmt->execute();
$result = $stmt->store_result();
$meta = $result->result_metadata();
echo "WORKS"; //doesn't print
while ($field = $meta->fetch_field())
$vars[] = &$data[$field->name];
call_user_func_array(array($result, 'bind_result'), $vars);
$i = 0;
while ($result->fetch()) {
$array[$i] = array();
foreach ($data as $k=>$v)
$array[$i][$k] = $v;
$i++;
}
print_r($array);
As using prepared statements bypasses the need for quotes and passes in the exact variable, you need to pass the wildcards in on your variable, not in the query:
$stmt = $conn->prepare("SELECT * FROM $table WHERE `$column` LIKE ?");
$stmt->bind_param("s", '%'.$line.'%');
i am using This code for showing user data record but this code is not work on my side
I want to echo out specific user data. I created a function where I insert multiple arguments (each argument represents a column in the database) and then echo whichever column I want with a simple line of code.
Index.php
include('function.php');
$conn = new MySQLi(localhost, root, password, database);
$user_id = $_SESSION['login_user']; // like 1
$user = user_data($conn, $user_id, 'login', 'pass', 'nikename', 'email');
if(empty($user)){
echo 'error'; // always showing this error
}else{
echo $user['nickename'];
}
Always Showing echo 'error';
function user_data($conn, $user_id){
$data = array();
$user_id = (int)$user_id;
$func_num_args = func_num_args();
$func_get_args = func_get_args();
if ($func_num_args > 1) {
unset($func_get_args[0]);
unset($func_get_args[1]);
$valid = array('login', 'pass', 'nikename', 'email');
$fields = array();
foreach($func_get_args as $arg) {
if(in_array($arg, $valid)) $fields[] = $arg;
}
$fields = '`' . implode ('`, `', $fields) . '`';
if($stmt = $conn->prepare("SELECT $fields FROM `users` WHERE `user_id` = ?")) {
$stmt->bind_param('si', $fields, $user_id);
$stmt->execute();
//here I am trying to convert the result into an array
$meta = $stmt->result_metadata();
while ($field = $meta->fetch_field()) {
$parameters[] = &$row[$field->name];
}
call_user_func_array(array($stmt, 'bind_result'), $parameters);
while ($stmt->fetch()) {
foreach($row as $key => $val) {
$x[$key] = $val;
}
$results[] = $x;
}
return $results;
$stmt->close();
}
}
}
Seeing and analyzing your code several times, I think the below will solve your issue.
Add this before your while/fetch loop
$row = array();
stmt_bind_assoc($stmt, $row);
so your code will look like this
$row = array();
stmt_bind_assoc($stmt, $row);
while ($stmt->fetch()) {
foreach($row as $key => $val) {
$x[$key] = $val;
}
$results[] = $x;
}
Also make sure you read the full documentation of bind_param on php.net here
Thanks and Best Regards
I guess, instead of
if($stmt = $conn->prepare("SELECT $fields FROM `users` WHERE `user_id` = ?")) {
$stmt->bind_param('si', $fields, $user_id);
you should go with
if($stmt = $conn->prepare("SELECT $fields FROM `users` WHERE `user_id` = ?")) {
$stmt->bind_param('i', $fields, $user_id);
Bind parameters. Types: s = string, i = integer, d = double, b = blob
As far as you have one argument with type INT you need to pass 'i' as a first parameters.
Try debugging over line by line in that function where you will get exact flaw by var_dump().
I am trying to return a multidimensional associative array from my MySql Database with the Format
$array[0]['user']
$array[0]['dateCompleted']
$array[0]['etc']
$array[1]['user']
$array[1]['dateCompleted']
$array[1]['etc']
...
Here is my code:
$mysqli = new mysqli(DBHOST, DBUSER, DBPASSWORD, DBDATABASE);
//Clean input
$idUser = trim($_SESSION['tmp01']);
/* create a prepared statement */
$stmt = $mysqli->prepare("SELECT user, dateCompleted, workType, workPrice FROM workDone WHERE user=? ORDER BY dateCompleted DESC");
/* bind parameters for markers */
$stmt->bind_param("i", $idUser);
$stmt->execute();
$data = $stmt->result_metadata();
$fields = array();
$row = array();
$rows = array();
$fields[0] = &$stmt;
$count = 1;
// this dynamically creates an array where each key is the name of the field.
while ($field = mysqli_fetch_field($data)) {
$fields[$count] = &$row[$field->name];
$count++;
}
// this calls bind_result() to each member of this $row array
call_user_func_array(array($stmt, 'bind_result'), $row); //<--problem
while ($stmt->fetch())
array_push($rows, $row);
$results = (count($rows) == 0) ? false : $rows;
//print_r($results);
return $results;
$stmt->close();
It works when I use the SQL statement "SELECT * FROM users ..."), but I overrun my servers memory by doing that. Instead I use the above code, but what it does it return a the same instance for each row I have.
In other words if I have four distinct rows in my MySQL database, it will return the first row four times.
P.S.
My server does not have mysqlnd enabled.
Your approach looks to be correct, but you seem to be passing incorrect arguments to call_user_func_array. Try this:
$data = $stmt->result_metadata();
$fields = array();
$currentrow = array();
$results = array();
// Store references to keys in $currentrow
while ($field = mysqli_fetch_field($data)) {
$fields[] = &$currentrow[$field->name];
}
// Bind statement to $currentrow using the array of references
call_user_func_array(array($stmt,'bind_result'), $fields);
// Iteratively refresh $currentrow array using "fetch", store values from each row in $results array
$i = 0;
while ($stmt->fetch()) {
$results[$i] = array(); //this is supposed to be outside the foreach
foreach($currentrow as $key => $val) {
$results[$i][$key] = $val;
}
$i++;
}
return $results;