I'm writing a function that takes three arguments, the first two arguments are strings but I want the third argument to comprise of multiple arguments.
Below is the block of code
function myFetch($query, $datatype, $variables){
include("models.php");
$stmt = $conn->prepare($query);
$stmt->bind_param($datatype, $variables);
$stmt->execute();
$result = $stmt->get_result();
return $result->fetch_assoc();
$stmt->close();
$conn->close();
}
From the above code, I'd like the third argument $variable to contain other arguments, example $variable = $one, $two, $three, $four of which these arguments have their own data to be passed to the bind_param function.
Example of the $query, $datatype and $variables:
$query = "SELECT * FROM table WHERE id = ? and visible = ?";
$datatype = "ii";
$id = 1,$visible = 1;
$variables = $id, $visible;
The solution would be like this:
Create an empty $param array and loop through your argument variable array $variables using a for loop.
In each iteration of the loop, push the elements to $variables array as a reference.
Use array_unshift() function to push $datatype to the beginning of $variables array.
Finally, use call_user_func_array() function to bind each of the parameters.
So your myFetch() function should be like this:
function myFetch($query, $datatype, $variables){
include("models.php");
$stmt = $conn->prepare($query);
$param = array();
$count = count($variables);
for($i = 0; $i < $count; ++$i){
$param[] = &$variables[$i];
}
array_unshift($param, $datatype);
call_user_func_array(array($stmt, 'bind_param'), $param);
$stmt->execute();
$result = $stmt->get_result();
$stmt->close();
$conn->close();
return $result;
}
Subsequently, you can call this function like this:
$query = "SELECT * FROM table WHERE id = ? and visible = ?";
$datatype = "ii";
$variables = array(1, 1);
$result = myFetch($query, $datatype, $variables);
while($row = $result->fetch_assoc()){
// display $row details
}
This should do everything you want in your function:
$query = "SELECT * FROM table WHERE id = ? and visible = ?";
$variables = array($id, $visible);
function myFetch($query, $variables){
include("models.php");
$stmt = $conn->prepare($query);
$stmt->execute($variables);
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
}
Just some thoughts:
Could you use include_once outside your function instead of include?
When you return a value before you close your connection, it will never get closed
Use Reflection to call mysqli::bind_param(), Example:
<?php
$resource = $db->prepare("SELECT * FROM table WHERE id = ? and visible = ?");
$reflectionArray = array(1,"yes");
$reflection = new ReflectionClass('mysqli_stmt');
$method = $reflection->getMethod("bind_param");
$method->invokeArgs($resource, $reflectionArray);
$resource->execute();
?>
Your function:
function myFetch($query, $datatype, $variablesArray){
include("models.php");
$stmt = $conn->prepare($query);
$reflection = new ReflectionClass('mysqli_stmt');
$method = $reflection->getMethod("bind_param");
$method->invokeArgs($stmt, $variablesArray);
$resource->execute();
$result = $stmt->get_result();
$stmt->close();
$conn->close();
return $result->fetch_assoc();
}
Related
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'm passing an array of values through a bind_param function, the way I do this is like this:
<?php
class Query{
private $_mysqli;
/*
* #param object $mysqli
*/
public function __construct($mysqli)
{
$this->_mysqli = $mysqli;
}
/*
* #param string query
* #param string $types
* #param array $values
*/
public function read($query = "", $type = "", $params = array())
{
$query = ($query === "") ? die("Read error: Query") : $query;
$type = ($type === "") ? die("Read error: Type") : array($type);
$params = (count($params) == 0) ? die("Read error: Params") : $params;
$values = array();
foreach($params as $key => $value) {
$values[$key] = &$params[$key];
}
if ($stmt = $this->_mysqli->prepare($query))
{
call_user_func_array(array($stmt, "bind_param"), array_merge($type, $values));
$stmt->execute();
$fields = array();
for($i=0; $i<count($params); $i++){
$fields[$i] = $params[$i];
}
call_user_func_array(array($stmt, "bind_result"), $fields);
$array = array();
while($data = $stmt->fetch())
{
$array[] = $data;
}
return $array;
}
}
}
This is the way I use my function
<?php
//$mysqli is the mysqli connection
$query = new Query($mysqli);
$query_str = "SELECT * FROM users WHERE voornaam = ? AND achternaam = ?";
$types = "ss";
$params = array("Firstname", "Lastname");
var_dump($query->read($query_str, $types, $params));
?>
The part where I get stucked is:
<?php
$fields = array();
for($i=0; $i<count($params); $i++){
$fields[$i] = $params[$i];
}
call_user_func_array(array($stmt, "bind_result"), $fields);
$array = array();
while($data = $stmt->fetch())
{
$array[] = $data;
}
?>
Im not sure where it goes wrong, I have a feeling at the while loop.
hope you guys can help me making this function working :)
you are binding results , so you don't need to assign your fetched data to new variable,
mysqli_stmt::bind_result -- mysqli_stmt_bind_result — Binds variables
to a prepared statement for result storage
while you are using call_user_func_array , and according to this comment, your loop :
while($data = $stmt->fetch())
{
$array[] = $data;
}
may be as follows:
while($stmt->fetch())
{
// params which you had bind it into bindParams
$array[] = $params;
}
I have this function which returns only one row, How can I modify the function so that it returns more than one row?
public function getVisitors($UserID)
{
$returnValue = array();
$sql = "select * from udtVisitors WHERE UserID = '".$UserID. "'";
$result = $this->conn->query($sql);
if ($result != null && (mysqli_num_rows($result) >= 1)) {
$row = $result->fetch_array(MYSQLI_ASSOC);
if (!empty($row)) {
$returnValue = $row;
}
}
return $returnValue;
}
There is a function in mysqli to do so, called fetch_all(), so, to answer your question literally, it would be
public function getVisitors($UserID)
{
$sql = "select * from udtVisitors WHERE UserID = ".intval($UserID);
return $this->conn->query($sql)->fetch_all();
}
However, this would not be right because you aren't using prepared statements. So the proper function would be like
public function getVisitors($UserID)
{
$sql = "select * from udtVisitors WHERE UserID = ?";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param("s", $UserID);
$stmt->execute();
$res = $stmt->get_result();
return $res->fetch_all();
}
I would suggest storing them in an associative array:
$returnValue = array();
while($row = mysqli_fetch_array($result)){
$returnValue[] = array('column1' => $row['column1'], 'column2' => $row['column2']); /* JUST REPLACE NECESSARY COLUMN NAME AND PREFERRED NAME FOR ITS ASSOCIATION WITH THE VALUE */
} /* END OF LOOP */
return $returnValue;
When you call the returned value, you can do something like:
echo $returnValue[0]['column1']; /* CALL THE column1 ON THE FIRST SET OF ARRAY */
echo $returnValue[3]['column2']; /* CALL THE column2 ON THE FOURTH SET OF ARRAY */
You can still call all the values using a loop.
$counter = count($returnValue);
for($x = 0; $x < $counter; $x++){
echo '<br>'.$rowy[$x]['column1'].' - '.$rowy[$x]['column2'];
}
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);
}
This function takes an array of integers
$this->grades
this array varies in size depending on what the user inputs.
I can get it to work perfectly with only one number, but when I try more than one I run into the problem. Do I need to somehow concatenate the responses together before encoding them? Or is there a more efficient way to run this?
private function retrieve_standards_one(){
$dbh = $this->connect();
for($x = 0; $x < (count($this->grades)); $x++){
$stmt = $dbh->prepare("SELECT code, standard_one_id
FROM standard_one
WHERE grade_id = :grade_id
ORDER BY standard_one_id");
$stmt->bindParam(':grade_id', $this->grades[$x], PDO::PARAM_STR);
$stmt->execute();
$stnd = $stmt->fetchAll(PDO::FETCH_ASSOC);
}
$json = json_encode($stnd);
return $json;
}
Just use an array to store the results and encode the array
private function retrieve_standards_one(){
$dbh = $this->connect();
$data = array();
for($x = 0; $x < (count($this->grades)); $x++){
$stmt = $dbh->prepare("SELECT code, standard_one_id
FROM standard_one
WHERE grade_id = :grade_id
ORDER BY standard_one_id");
$stmt->bindParam(':grade_id', $this->grades[$x], PDO::PARAM_STR);
$stmt->execute();
$data[] = $stmt->fetchAll(PDO::FETCH_ASSOC);
}
$json = json_encode($data);
return $json;
}
The problem is this:
$stnd = $stmt->fetchAll(PDO::FETCH_ASSOC);
Each time you go through the loop, you overwrite the contents of $stnd. So yes, in order for it to work properly, you'd need to instead append each individual result to an overall array, and then encode the array.
Here's a rewritten version of your function that both utilizes an array and also doesn't unnecessarily re-prepare the query each loop iteration:
private function retrieve_standards_one(){
$dbh = $this->connect();
$stmt = $dbh->prepare("SELECT code, standard_one_id
FROM standard_one
WHERE grade_id = :grade_id
ORDER BY standard_one_id");
$stnd = array();
for($x = 0; $x < (count($this->grades)); $x++){
$stmt->bindParam(':grade_id', $this->grades[$x], PDO::PARAM_STR);
$stmt->execute();
$stnd[] = $stmt->fetchAll(PDO::FETCH_ASSOC);
}
return json_encode($stnd);
}
Note: the $stnd = array(); line is not strictly necessarily, but it'll prevent things from crashing if $this->grades ever has 0 elements in it.
If you’re wanting to pass an array of numbers, then you can do this:
<?php
$grades = array(1,2,3,4,5);
private function retrieve_standards_one($grades)
{
// ensure only numbers get into the SQL statement
$grade_ids = array();
foreach ($grades as $grade) {
if (is_numeric($grade)) {
$grade_ids[] = $grade;
}
}
$grade_ids = implode(',', $grade_ids);
$dbh = $this->connect();
$sql = "SELECT code, standard_one_id
FROM standard_one
WHERE grade_id IN ($grade_ids)
ORDER BY standard_one_id";
$stmt = $dbh->query($sql);
$stmt->execute();
$stnd = $stmt->fetch(PDO::FETCH_ASSOC);
$json = json_encode($stnd);
return $json;
}