Getting a multi dimensional array from a mysql database - php

Right now im using Mysqli to retrieve data from a Mysql Database, The code im using is difficult to understand and from my understanding has depreciated functions or itself in entire is depreciated.
If i could get some insight and maybe some updated techniques on my Qoal of retrieving data from a mysql DB.
mysqli prepared statements
What i have so far is this:
$param = 1;
$mysqli = new mysqli("127.0.0.1", "user", "password", "databaseName");
$mysqli->query('SELECT reply_id FROM replies WHERE reply_topic = ? ORDER BY reply_date ASC');
$mysqli->bind_param('i',$param)
$mysqli->execute();
$row = bind_result_array($mysqli);
while($mysqli->fetch()){
$set[$row['']] = getCopy($row);
}
$mysqli->free_result();
return $set;
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;
}
function getCopy($row)
{
return array_map(create_function('$a', 'return $a;'), $row);
}

You need to clean up the call on the database first. $mysqli->query has send the query before you bound parameters and so on.
Replace with the following;
$stmt = $mysqli->prepare('SELECT reply_id FROM replies WHERE reply_topic = ? ORDER BY reply_date ASC');
$stmt->bind_param('i',$param)
$stmt->execute();
The $mysqli->prepare returns a new object that you should bind values to and then execute. It avoids SQL injection!
None of this is depreciated. mysqli_ is exactly what you should use.
As all you want is an array of the results, you can use the following code to do so - no user functions required.
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
$set[] = $row['reply_id'];
}
For each row in the while, each field is saved into an array with the column name as the key. So $row['reply_id'] contains the value of the reply_id column in the database. Above I have saved this value to an array called $set, and when it loops over the next result row it saves the next value to that array too.
You can manipulate the result before or after saving it to the new array, as you see fit.
Hope this helps.

Related

How to check if column equals a value and do somthing if true? [duplicate]

This question already has answers here:
Single result from database using mysqli
(6 answers)
Closed 2 years ago.
I am trying to write a function that will check for a single value in the db using mysqli without having to place it in an array. What else can I do besides what I am already doing here?
function getval($query){
$mysqli = new mysqli();
$mysqli->connect(HOST, USER, PASS, DB);
$result = $mysqli->query($query);
$value = $mysqli->fetch_array;
$mysqli->close();
return $value;
}
How about
$name = $mysqli->query("SELECT name FROM contacts WHERE id = 5")->fetch_object()->name;
The mysql extension could do this using mysql_result, but mysqli has no equivalent function as of today, afaik. It always returns an array.
If I didn't just create the record, I do it this way:
$getID = mysqli_fetch_assoc(mysqli_query($link, "SELECT userID FROM users WHERE something = 'unique'"));
$userID = $getID['userID'];
Or if I did just create the record and the userID column is AI, I do:
$userID = mysqli_insert_id($link);
Always best to create the connection once at the beginning and close at the end. Here's how I would implement your function.
$mysqli = new mysqli();
$mysqli->connect(HOSTNAME, USERNAME, PASSWORD, DATABASE);
$value_1 = get_value($mysqli,"SELECT ID FROM Table1 LIMIT 1");
$value_2 = get_value($mysqli,"SELECT ID FROM Table2 LIMIT 1");
$mysqli->close();
function get_value($mysqli, $sql) {
$result = $mysqli->query($sql);
$value = $result->fetch_array(MYSQLI_NUM);
return is_array($value) ? $value[0] : "";
}
Here's what I ended up with:
function get_col($sql){
global $db;
if(strpos(strtoupper($sql), 'LIMIT') === false) {
$sql .= " LIMIT 1";
}
$query = mysqli_query($db, $sql);
$row = mysqli_fetch_array($query);
return $row[0];
}
This way, if you forget to include LIMIT 1 in your query (we've all done it), the function will append it.
Example usage:
$first_name = get_col("SELECT `first_name` FROM `people` WHERE `id`='123'");
Even this is an old topic, I don't see here pretty simple way I used to use for such assignment:
list($value) = $mysqli->fetch_array;
you can assign directly more variables, not just one and so you can avoid using arrays completely. See the php function list() for details.
This doesn't completely avoid the array but dispenses with it in one line.
function getval($query) {
$mysqli = new mysqli();
$mysqli->connect(HOST, USER, PASS, DB);
return $mysqli->query($query)->fetch_row()[0];
}
First and foremost,
Such a function should support prepared statements
Otherwise it will be horribly insecure.
Also, such a function should never connect on its own, but accept an existing connection variable as a parameter.
Given all the above, only acceptable way to call such a function would be be like
$name = getVal($mysqli, $query, [$param1, $param2]);
allowing $query to contain only placeholders, while the actual data has to be added separately. Any other variant, including all other answers posted here, should never be used.
function getVal($mysqli, $sql, $values = array())
{
$stm = $mysqli->prepare($sql);
if ($values)
{
$types = str_repeat("s", count($values));
$stm->bind_param($types, ...$values);
}
$stm->execute();
$stm->bind_result($ret);
$stm->fetch();
return $ret;
}
Which is used like this
$name = getVal("SELECT name FROM users WHERE id = ?", [$id]);
and it's the only proper and safe way to call such a function, while all other variants lack security and, often, readability.
Try something like this:
$last = $mysqli->query("SELECT max(id) as last FROM table")->fetch_object()->last;
Cheers

Accessing a MySQL Link Identifier from within a Function

I'm having some difficulty returning an array out of a while lopp which I have in a function. Here is the code I am using. I am meant to be able to return an array of results from the function which contains the id numbers of pictures associated with a particular user id - in this case I want to print_r the array for the user id of 17. When this code isn't in the function it works, but when I place it in the function, no luck. I presume its related to a mistake I am making in the returning of the array. Your help is greatly appreciated.
function picture($id)
{
$sql = "SELECT * FROM avatar WHERE user_id={$id}";
$result = $database->query($sql);
$results = array();
while ($row = mysql_fetch_assoc($result))
{
$results[] = $row;
}
return $results;
}
$results = picture(17);
print_r($results);
Your function can't access your MySQL link identifier
First of all, you're mixing object-oriented paradigm ($database->query($sql)) with procedural paradigm (mysql_fetch_assoc($result)) which will make your code a nightmare to maintain.
Assuming that $database is a mysql_ link identifier, you'll need to pass it into your function in order to access it there.
function getUserAvatar($database, $id){
$sql = 'SELECT * FROM `avatar` WHERE `user_id`=' . intval($id) . ' LIMIT 1;';
$result = mysql_query($database, $sql);
$row = mysql_fetch_assoc($result);
return $row;
}
$results = picture($database, 17);
Don't just copy-paste that, keep reading!
The above will probably work, but if you're allowing a user to pass that user ID into the function, it's quite possible that they'll be able to find a vulnerability to inject an SQL statement of their choice into your MySQL database.
mysql_ functions are deprecated, so you should ideally stop using them and switch to mysqli or PDO. You'll also want to get an understanding of prepared statements in order to prevent SQL injections. If you can't upgrade, look at the mysql_real_escape_string and intval functions and make sure you sanitize all user inputs before processing them.
The resulting code will look something like this, if you switch to mysqli and prepared statements:
function getUserAvatar($db, $userId) {
$stmt = $db->prepare("SELECT * FROM `avatar` WHERE `user_id`=? LIMIT 1;");
$stmt->bind_param("i", $userId);
$stmt->execute();
$res = $stmt->get_result();
return $res->fetch_assoc();
}
$db = new mysqli("localhost", "user", "password", "database");
$result = getUserAvatar($db, 17);
may be you should try this..
function picture($id)
{
$sql = "SELECT * FROM avatar WHERE user_id={$id}";
$result = $database->query($sql);
$row = mysql_fetch_assoc($result);
return $row;
}
$results = picture(17);
print_r($results);

PHP MySQLi prepared statements and fetching subset of columns

I am using MySQLi and PHP to call a stored MySQL routine with prepared statements. It returns a result set with dozens of columns.
$stmt = $dbconnection->prepare("CALL SomebodysDbProcedure(?);");
$stmt->bind_param("s", $idvalue);
$stmt->execute();
$stmt->bind_result($col1, $col2, $col3, ...);
However, I am only interested in a subset of the output columns.
The documentation says bind_result() is required to handle the complete set of returned columns:
Note that all columns must be bound after mysqli_stmt_execute() and
prior to calling mysqli_stmt_fetch().
Do I need to add code also for those columns I'm uninterested in? If so the application will break if the MySQL stored routine result set is expanded in the future, or even columns rearranged. Is there a workaround for this?
I'm assuming that you just don't want to write out all those variables for the bind_result() function. You could use a function like below instead of the bind_result() function. Pass it your $stmt object and you'll get back an array of standard objects with the fields you want.
function getResult($stmt)
{
$valid_fields = array('title', 'date_created'); // enter field names you care about
if (is_a($stmt, 'MySQLi_STMT')) {
$result = array();
$metadata = $stmt->result_metadata();
$fields = $metadata->fetch_fields();
for (; ;)
{
$pointers = array();
$row = new \stdClass();
$pointers[] = $stmt;
foreach ($fields as $field)
{
if (in_array($field->name, $valid_fields)) {
$fieldname = $field->name;
$pointers[] = &$row->$fieldname;
}
}
call_user_func_array('mysqli_stmt_bind_result', $pointers);
if (!$stmt->fetch())
break;
$result[] = $row;
}
$metadata->free();
return $result;
}
return array();
}
The answer of Jonathan Mayhak guided me in the right direction. On PHP bind_result page, nieprzeklinaj provides a function called fetch(). It works; use it like this:
$stmt = $conn->prepare("CALL SomebodysDbProcedure(?);");
$stmt->bind_param("s", $idvalue);
$stmt->execute();
$sw = (array)(fetch($stmt));
$s = $sw[0]; // Get first row
$dateCreated = $s['date_created']; // Get field date_created
Edit: Unfortunately successive calls within the same PHP file don't seem to work with this method.
Try using fetch_fields php method:
array mysqli_fetch_fields ( mysqli_result $result )
http://php.net/manual/en/mysqli-result.fetch-fields.php

Updating a MySQL database via PDO and tokens - all parameters being set to last value in dataset

As the title states: I am trying to update specific records in a MySQL data base using PDO and tokens to secure against any injection.
Here is my code:
Some arrays to help build the query:
$id = 1234
$values = array ('a','b','c',);
$variables = array ($A, $B, $C);
The query built via loop:
$sql = "UPDATE table1 SET ";
foreach($values as $value)
{
$sql .="$value = :$value, ";
}
$sql = rtrim($sql,', ');
$sql .=" WHERE id = '$id'";
Execution of query via PDO:
try
{
$pdo = new PDO('mysql:host=localhost; dbname=db01', $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $pdo->prepare($sql);
foreach(array_combine($values, $variables) as $value=>$variable)
{
$stmt->bindParam(":$value", $variable);
}
$stmt->execute();
The result:
Every field in the specified record (matching $id) is set to the same value, which is always equal to the contents of the last variable listed in the array (in this example they would all contain the value held in $C)
echoing the SQL query shows it has been constructed correctly.
Any ideas? Thanks for your consideration
Extending from comment:
In your foreach loop, the $variable is a value, not a reference, so when you mysqli_stmt::execute(), you actually end up using the last $variable.
To avoid that, you'll have to use something like this:
$cache=array_combine($values,$variables);
foreach($cache as $value=>$variable)
{
$stmt->bindParam(":$value",$cache[$value]);
}
You have to make this way:
foreach(array_combine($values, $variables) as $value=>$variable)
{
$stmt->bindParam(":$value", $variable);
$stmt->execute();
}
Execute your query inside the for loop. Don't execute your query once the loop is done because it will only get the last value of your array. It will only execute once.

Is it possible to use mysqli_fetch_object with a prepared statement

All the examples I see using mysqli_fetch_object use mysql_query(), I cannot get it to work with prepared statements. Does anyone know what is wrong with this code snippet, as fetch_object returns null.
$sql = "select 1 from dual";
printf("preparing %s\n", $sql);
$stmt = $link->prepare($sql);
printf("prepare statement %s\n", is_null($stmt) ? "is null" : "created");
$rc = $stmt->execute();
printf("num rows is %d\n", $stmt->num_rows);
$result = $stmt->result_metadata();
printf("result_metadata %s\n", is_null($result) ? "is null" : "exists");
$rc = $result->fetch_object();
printf("fetch object returns %s\n", is_null($rc) ? "NULL" : $rc);
$stmt->close();
The output is:
preparing select 1 from dual
prepare statement created
num rows is 0
result_metadata exists
fetch object returns NULL
This is the code I use to create an object from a prepared statement.
It could perhaps be used in a subclass of mysqli?
$query = "SELECT * FROM category WHERE id = ?";
$stmt = $this->_db->prepare($query);
$value = 1;
$stmt->bind_param("i", $value);
$stmt->execute();
// bind results to named array
$meta = $stmt->result_metadata();
$fields = $meta->fetch_fields();
foreach($fields as $field) {
$result[$field->name] = "";
$resultArray[$field->name] = &$result[$field->name];
}
call_user_func_array(array($stmt, 'bind_result'), $resultArray);
// create object of results and array of objects
while($stmt->fetch()) {
$resultObject = new stdClass();
foreach ($resultArray as $key => $value) {
$resultObject->$key = $value;
}
$rows[] = $resultObject;
}
$stmt->close();
MySql Native Driver extension (mysqlnd), has the get_result method:
$stmt->execute();
$obj = $stmt->get_result()->fetch_object();
I don't believe the interface works like that.
Going by the documentation and examples (http://www.php.net/manual/en/mysqli.prepare.php) it seems that $stmt->execute() does not return a resultset, but a boolean indicating success / failure (http://www.php.net/manual/en/mysqli-stmt.execute.php). To actually get the result, you need to bind variables to the resultset (aftere the execute call) using $stmt->bind_result (http://www.php.net/manual/en/mysqli-stmt.bind-result.php).
After you did all that, you can do repeated calls to $stmt->fetch() () to fill the bound variables with the column values from the current row. I don't see any mention of $stmt->fetch_object() nor do I see how that interface could work with a variable binding scheme like described.
So this is the story for "normal" result fetching from mysqli prepared statments.
In your code, there is something that I suspect is an error, or at least I am not sure you intended to do this.
You line:
$result = $stmt->result_metadata();
assignes the resultset metadata, which is itself represented as a resultset, to the $result variable. According to the doc (http://www.php.net/manual/en/mysqli-stmt.result-metadata.php) you can only use a subset of the methods on these 'special' kinds of resultsets, and fetch_object() is not one of them (at least it is not explicitly listed).
Perhaps it is a bug that fetch_object() is not implemented for these metadata resultsets, perhaps you should file a bug at bugs.mysql.com about that.

Categories