MySQLi Prepared statements and fetching fields - php

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.'%');

Related

PHP trying to simply a repetitive script involving rowsets

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);

fetch multiple rows of same id in different variable

I have two rows contaning data of same id.
It has different adresses in different rows for the same id.
I want to fetch both the adress in different variable in php.
How can i do this? Please help!
Below is the code:
foreach($row_address as $address)
{
echo "<br> Address :" .$address;
$info=Array();
$data=explode(' ', $address );
$info[1]=$data[0];
$info[2]=$data[1];
$info[3]=$data[2];
echo "City :".$info[1];
echo "Country :".$info[2];
echo "Pin Code :".$info[3];
}
function hoteladdresstable($id)
{
global $conn;
/*$sql2 = "select AddressLine from hoteladdress where Hotel_Id= " .$id;
$result2 = mysql_query($sql2,$conn);
$row2 = mysql_fetch_assoc($result2,MYSQL_NUM);
return $row2;*/
$query = "select AddressLine from hoteladdress where Hotel_Id = " .$id;
$result = mysql_query($query);
while ($row = mysql_fetch_assoc($result))
{
$d[] = $row['AddressLine'];
}
return $d;
}
It gives me both the address of the same id in one variable only.
I want them in two different variables.
You are already getting an array of addresses in $d.
What you can do is:
$d = array();
while ($row = mysql_fetch_assoc($result)) {
$d[$row['Address_ID']] = $row['AddressLine'];
}
extract($d, EXTR_PREFIX_ALL, 'ad');
If you have address ids 2 and 4, you will get two variables
$ad_2 and $ad_4
You should use parameterized queries. Use PHP's PDO:
$DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
$STH = $DBH->prepare('select AddressLine from hoteladdress where Hotel_Id = :id');
$STH->bindParam(':name', $id);
$STH->execute();
$d = array();
while($row = $STH->fetch()) {
$d[] = $row['AddressLine'];
}
http://code.tutsplus.com/tutorials/why-you-should-be-using-phps-pdo-for-database-access--net-12059
Don't want your queries getting injected with attacks.
I suggest you to use mysqli instead.
$data = array();
while($row = mysqli_fetch_assoc($result)){
$data[] = $row;
}
return $data;
and then
foreach($data as $oneRow){
echo $oneRow['AddressLine']; //and all other stuff that you want.
}
you can verify it:
print_r($data);

Getting an assoc or numeric array from a MySQLi prepared statement NOT WORKING

I can't getting an assoc or numeric array from a mysqli prepared statement. I searched and researched from code to get it but it have been imposible. I generate this code based on all that codes. I really think that's correct but it doesn't work anyway:
$id = '134610';
$sql = "SELECT * FROM table WHERE id = ?";
$stmt = $mysqli->stmt_init();
$stmt->prepare($sql);
$stmt->bind_param("i", $id);
$stmt->execute();
$result = $stmt->get_result();
while ($array = $result->fetch_array(MYSQLI_ASSOC))
// or fetch_array(MYSQLI_NUM))
print_r($array);
MYSQLI_ASSOC
Columns are returned into the array having the fieldname as the array index.
MYSQLI_NUM
Columns are returned into the array having an enumerated index.
http://php.net/manual/en/mysqli.constants.php
I finally resolve it with that code:
$id = '134610';
$sql = "SELECT * FROM table WHERE id = ?";
$stmt = $mysqli->stmt_init();
$stmt->prepare($sql);
$stmt->bind_param("i", $id);
$stmt->execute();
$array = self::bind_result_array($stmt);
for($i=0;$stmt->fetch();$i++)
$ArrayOfArrays[$i] = self::getCopy($array);
$stmt->close();
return $ArrayOfArrays;
and this two functions:
public function bind_result_array($stmt)
{
$meta = $stmt->result_metadata();
$result = array();
while ($field = $meta->fetch_field())
{
$result[$field->name] = NULL;
$params[] = &$result[$field->name];
}
call_user_func_array(array($stmt, 'bind_result'), $params);
return $result;
}
public function getCopy($row)
{
return array_map(create_function('$a', 'return $a;'), $row);
}

Mysqli with unknown bind_results

Ok, I thought I had this, but I can't see why it's not working...
I have a SELECT with a variable table, hence my columns (bind_result) is going to be variable.
I need to adjust for any number of columns coming back, and fetch as an associated array, since there will be multiple rows coming back:
// Get table data
$mysqli = new mysqli('host','login','passwd','db');
if ($mysqli->connect_errno()) { $errors .= "<br>Cannot connect: ".$mysqli->connect_error()); }
$stmt = $mysqli->prepare("SELECT * FROM ?");
$stmt->bind_param('s', $table);
$stmt->execute();
// Get bind result columns
$fields = array();
// Loop through columns, build bind results
for ($i=0; $i < count($columns); $i++) {
$fields[$i] = ${'col'.$i};
}
// Bind Results
call_user_func_array(array($stmt,'bind_result'),$fields);
// Fetch Results
$i = 0;
while ($stmt->fetch()) {
$results[$i] = array();
foreach($fields as $k => $v)
$results[$i][$k] = $v;
$i++;
}
// close statement
$stmt->close();
Any thoughts are greatly appreciated ^_^
EDIT: New code:
$mysqli = new mysqli('host','login','passwd','db');
if ($mysqli->connect_errno)) { $errors .= "<br>Cannot connect: ".$mysqli->connect_error()); }
$stmt = "SELECT * FROM ".$table;
if ($query = $mysqli->query($stmt)) {
$results = array();
while ($result = $query->fetch_assoc()) {
$results[] = $result;
}
$query->free();
}
$mysqli->close();
You can not bind the table name. Bind_param accept the column name and its datatype.
To use the table name dynamically use the below code:
$stmt = $mysqli->prepare("SELECT * FROM ".$table);

Returning multi-dimensional associative array with mysqli prepared statements

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;

Categories