Insert values to db with iterations - php

so here I'm trying to make an insert function which will be dynamic. By dynamic I mean that it can insert into any table and n number of columns. I'm making this function so that I don't have to write multiple functions to insert whenever I have to insert into different table or increase number of columns.
In my function, I'm passing 2 parameters. One is the tablename and second is the array of columns and their values in this way.
$arr = array("customerid" => "123",
"email" => "asa");
And here's my function :-
function insert_tester($table,$arr)
{
global $conn;
$val=0;
try
{
$s = $conn->prepare("INSERT INTO $table(" . foreach($arr as $column => $valule) {$column.","} . ")
VALUES(" . foreach($arr as $column => $value) {':val'.$val++} . ")");
$val=0;
foreach($arr as $column => $value)
{
$s->bindParam(":val$val", $value);
$val++;
}
if($s->execute())
{
return true;
}
else
{
return false;
}
}
catch(PDOException $e)
{
echo $e->getMessage();
}
}//function
But unfortunately my function doesn't work, it says foreach not expected.
What would be the best and right way to achieve my target ?

This is what you exactly need, here $db is your PDO database connection object
function insert_tester($db, $table, $arr) {
$fields = array_keys($arr);
$values = array_values($arr);
//build the fields
$buildFields = '';
if (is_array($fields)) {
//loop through all the fields
foreach ($fields as $key => $field) {
if ($key == 0) {
//first item
$buildFields .= $field;
} else {
//every other item follows with a ","
$buildFields .= ', ' . $field;
}
}
} else {
//we are only inserting one field
$buildFields .= $fields;
}
//build the values
$buildValues = '';
if (is_array($values)) {
//loop through all the fields
foreach ($values as $key => $value) {
if ($key == 0) {
//first item
$buildValues .= '?';
} else {
//every other item follows with a ","
$buildValues .= ', ?';
}
}
} else {
//we are only inserting one field
$buildValues .= ':value';
}
$prepareInsert = $db->prepare('INSERT INTO ' . $table . '(' . $buildFields . ') VALUES (' . $buildValues . ')');
//execute the update for one or many values
if (is_array($values)) {
$prepareInsert->execute($values);
} else {
$prepareInsert->execute(array(':value' => $values));
}
//record and print any DB error that may be given
$error = $prepareInsert->errorInfo();
if ($error[1]) {
print_r($error);
} else {
return true;
}
}

Since you're using PDO, there's an easier way:
$names = join(',', array_keys($arr));
$values = substr(str_repeat(',?', count($arr)), 1);
$s = $conn->prepare("INSERT INTO $table ($names) VALUES ($values)");
if ($s->execute(array_values($arr))) {
return true;
}
This assumes your array keys and $table are valid table or column names in SQL.

I actually created a class that extends PDO just so that I could do what you want to do. Use this class instead of PDO when you instantiate your database connection. Then, you'll be able to use the insert, update, and delete methods directly on the database connection instance (i.e. $conn->insert('sometable', array() ); ).
I use this class quite frequently and thought you might appreciate the bonus methods besides insert($table, $data):
class DatabaseConnection extends PDO {
public function insert($table, $data) {
$fields = implode(", ", array_keys($data));
$questionMarks = rtrim( str_repeat("?, ", count($data)), ", ");
$stmt = $this->prepare("INSERT INTO $table ($fields) VALUES ($questionMarks)");
foreach (array_values($data) as $key => $value) {
$stmt->bindValue($key+1, $value);
}
//return $stmt;
return $stmt->execute();
}
public function update($table, $data, $conditions) {
$fields = implode("=?, ", array_keys($data))."=?";
foreach ($conditions as $column => $condition) {
if (empty($whereClause)) {
$whereClause = "$column=?";
} else {
$whereClause .= " AND $column=?";
}
$data[] = $condition;
}
$stmt = $this->prepare("UPDATE $table SET $fields WHERE $whereClause");
foreach (array_values($data) as $key => $value) {
$stmt->bindValue($key+1, $value);
}
//return $stmt;
return $stmt->execute();
}
public function delete($table, $conditions) {
$data = array();
foreach ($conditions as $column => $condition) {
if (empty($whereClause)) {
$whereClause = "$column=?";
} else {
$whereClause .= " AND $column=?";
}
$data[] = $condition;
}
$stmt = $this->prepare("DELETE FROM $table WHERE $whereClause");
foreach (array_values($data) as $key => $value) {
$stmt->bindValue($key+1, $value);
}
//return $stmt;
return $stmt->execute();
}
}

Try an implode on the keys
implode(', ', array_keys($arr));
And for your bindParms you can be clever and try
implode(', :', array_keys($arr));
You'll have to prefix the first one but that should get you on the right track

Related

Error (SQLSTATE[HY000]: General error) in oop

I start to get this error when i add something in database i know what the problem but i tried to solve it but i could not
part of database class:
public function query($sql, $params = array()) {
$this->_error = FALSE;
$this->_query = $this->_conn->prepare($sql);
if ($this->_query) {
if (count($params)) {
$x = 1;
foreach ($params as $param) {
$this->_query->bindValue($x, $param);
$x++;
}
}
if ($this->_query->execute()) {
$this->_result = $this->_query->fetchAll(PDO::FETCH_OBJ);
$this->_count = $this->_query->rowCount();
} else {
return $this->_error = TRUE;
}
}
return $this;
}
public function insert($table, $fields = array()){
$keys = array_keys($fields);
$value = NULL;
$x = 1;
foreach ($fields as $field) {
$value .= '?';
if ($x < count($fields)) {
$value .=' , ';
}
$x++;
}
$sql = 'INSERT INTO ' . $table . '(`' . implode('`,`', $keys) . '`) VALUES (' . $value . ')';
if (!$this->query($sql, $fields)->error()) {
return TRUE;
}
return FALSE;
}
this when i insert the data in database
try {
$db->insert('users', array('username' => $_POST['username'],
'password' => $pass_hash,
'Group' => 0));
} catch (Exception $ex) {
die($ex->getMessage());
}
everything work fine and code insert the data in database but problem i get this error (SQLSTATE[HY000]: General error) because i am trying to fetch the data and i should not fetch it but i want my class be more dynamic , what the way i can fix this ? and thank you
problem form this line
$this->_result = $this->_query->fetchAll(PDO::FETCH_OBJ);

PDO database class selection function with prepared where clauses

I am trying to make a PDO database class with prepared statements but I seemed to have gotten my self stuck at the select function. I have tried allot of things but it just would always end up giveing me errors. I am also very sorry about the fact that I am not spesific at what actualy goes wrong.
Current errors:
Notice: Array to string conversion in
D:\wamp64\www\PDOtest\databaseClassTest.php on line 136
Notice: Array
to string conversion in D:\wamp64\www\PDOtest\databaseClassTest.php on
line 137
Fatal error: Call to a member function fetchAll() on boolean in
D:\wamp64\www\PDOtest\databaseClassTest.php on line 166
<?php
class database {
private $handler;
public function __construct($databaseType,$host,$dbname,$username,$password) {
$this->handler = new PDO("{$databaseType}:host={$host};dbname={$dbname}", $username, $password);
}
public function insert($table, $columnsArrayAndValues) {
$sql = "INSERT INTO {$table} ("; // Make the first part of the Insert query with the table and (. example "INTERT INTO post (";
$countColums = count($columnsArrayAndValues);//make a variable to hold the amount of colums which the user provides with the array.
/*
if the array is
array(
':message' => $message,
':user_ID' => $user_ID,
':board_ID' => $board_ID
)
this would return 3 because it has 3 elements
*/
$i = 0; //initialize an iterator
foreach($columnsArrayAndValues as $colum => $value) { // cut the colums array into parts and loop threw them
$i++; // add one to the iterator
if($i < $countColums){ //if the Iterator is smallen then the amount of colums
$sql .= $colum . ", "; // add the colum name to the sql string and add a ,
// i do this because when you have multipe colums you need an , to differentiate the colums
} else {
$sql .= $colum . ")";// the last ellement should not have an ,!!!!!!!!!!!!!!!!!!! it should also have an ) at the end of the colum declartion
}
}
$sql .= " VALUES ("; // add the values clause...
$i = 0; // reset the iterator
foreach($columnsArrayAndValues as $colum => $value) { // cut the colums array into parts and loop threw them
$i++; // add one to the iterator
if($i < $countColums){ //if the Iterator is smallen then the amount of colums
$sql .= ":{$colum}, "; // add the prepared name to the sql string and add a ,
// i do this because when you have multipe prepared names you need an , to differentiate the colums
} else {
$sql .= ":{$colum})"; /// the last element should not have an ,......
}
}
$query = $this->handler->prepare($sql); //prepare the statement
$ar = array(); //initialize an array
foreach($columnsArrayAndValues as $colum => $value) { // cut the colums array into parts and loop threw them
$ar[":{$colum}"]= $value; // make the link...
}
$query->execute($ar);// execute the query
}
public function select($fieldAndTableArray, $where = NULL) {
$sql = "SELECT ";
$fieldAndTableArray;
$countTabels = count($fieldAndTableArray);//make a variable to hold the amount of colums which the user provides with the array.
/*
if the array is
array(
"tabel" => array("colum1a", "colum2a", "colum3a", "colum4a"),
"tabel2" => array("colum1b", "colum2b", "colum3b", "colum4b")
)
this would return 2 because it has 2 elements
*/
foreach($fieldAndTableArray as $table => $fields){ // cut the colums array into parts and loop threw them
$countFields = count($fields);//make a variable to hold the amount of colums which the user provides with the array.
$i =0;
foreach($fields as $field) {
$i++;
$sql .= "`{$table}`.`{$field}`";
if($i <= $countFields) {
$sql .= ", ";
}
}
}
$sql .= " FROM ";
$i = 0;
foreach($fieldAndTableArray as $table => $fields){ // cut the colums array into parts and loop threw them
$i++;
$sql .= "`{$table}`";
if($i < $countTabels) {
$sql .=", ";
}
}
if($where != NULL) {
$sql .= " WHERE ";
if(is_array($where)) {
foreach($where as $wherePart) {
if(is_array($wherePart)) {
$elementCounter = 0;
foreach($wherePart as $element){
$elementCounter++;
if($elementCounter >= 3){
$sql .= ":{$element}";
} else {
$sql .= $element . " ";
}
}
} else {
$sql .= $wherePart . " ";
}
}
} else {
$sql .= $where;
}
}
if(is_array($where)) {
$ar = array(); //initialize an array
foreach($where as $wherePart=>$value) {
if(is_array($wherePart)) {
$elementCounter = 0;
foreach($wherePart as $element){
$elementCounter++;
if($elementCounter >= 3){
$ar[":{$colum}"]= $value; // make the link...
}
}
}
}
}
$query = $this->handler->prepare($sql); //prepare the statement
foreach($where as $colum => $value) { // cut the colums array into parts and loop threw them
$ar[":{$colum}"]= $value; // make the link...
}
$query->execute($ar);// execute the query
return $query->execute($ar);// execute the query
}
}
$db = new database("mysql", "127.0.0.1", "imageboard", "root", "");
//$db->insert("post", array("message"=>"Hello i am a message from PDO", "user_ID"=>(int)1, "board_ID"=>(int)2));
/*var_dump($db->select(
array(
"tabel" => array("colum1a", "colum2a", "colum3a", "colum4a"),
"tabel2" => array("colum1b", "colum2b", "colum3b", "colum4b")
),
array(
array("colum1a", "=", "banaan"), "AND",
array("colum1b", "!=", "24")
)
));*/
echo "deze werkt goed->";
$result = $db->select(
array(
"post" => array("post_ID", "post_name", "image_ID", "message"),
"image" => array("image_path")
),
array(
array("`post`.`image_ID`", "=", "`image`.`image_ID`")
)
);
var_dump($result);
while($row = $result->fetchAll())
{
echo $row['message'].'<br>';
}
?>
I spent some time looking at the code and came up with this
<?php
class Database {
private static $handler;
private $db;
protected function __construct() {
try {
$this->db = new PDO('mysql:host=' . Config::get('mysql/host') . ';dbname=' . Config::get('mysql/database'), Config::get('mysql/username'), Config::get('mysql/password'));
} catch(PDOException $e) {
die($e->getMessage());
}
}
public static function getInstance() {
if(!isset(self::$handler)) { //if there is no instance jet we want to make an instance one would also use this to excute things methods inside this this class
self::$handler = new Database();
}
return self::$handler; //return the instance
}
public function insert($table, $columnsArrayAndValues) {
$sql = "INSERT INTO `{$table}` ("; // Make the first part of the Insert query with the table and (. example "INTERT INTO post (";
$countColums = count($columnsArrayAndValues);//make a variable to hold the amount of colums which the user provides with the array.
/*
if the array is
array(
':message' => $message,
':user_ID' => $user_ID,
':board_ID' => $board_ID
)
this would return 3 because it has 3 elements
*/
$i = 0; //initialize an iterator
foreach($columnsArrayAndValues as $colum => $value) { // cut the colums array into parts and loop threw them
$i++; // add one to the iterator
if($i < $countColums){ //if the Iterator is smallen then the amount of colums
$sql .= "`{$colum}`, "; // add the colum name to the sql string and add a ,
// i do this because when you have multipe colums you need an , to differentiate the colums
} else {
$sql .= "`{$colum}`)";// the last ellement should not have an ,!!!!!!!!!!!!!!!!!!! it should also have an ) at the end of the colum declartion
}
}
$sql .= " VALUES ("; // add the values clause...
$i = 0; // reset the iterator
foreach($columnsArrayAndValues as $colum => $value) { // cut the colums array into parts and loop threw them
$i++; // add one to the iterator
if($i < $countColums){ //if the Iterator is smallen then the amount of colums
$sql .= "?, "; // add the prepared name to the sql string and add a ,
// i do this because when you have multipe prepared names you need an , to differentiate the colums
} else {
$sql .= "?)"; /// the last element should not have an ,......
}
}
$ar = array(); //initialize an array
foreach($columnsArrayAndValues as $colum => $value) { // cut the colums array into parts and loop threw them
$ar[]= $this->replaceQuotesAndBackslashes($value); // make the link...
}
if($this->action($sql, $ar)) {
return $this->db->lastInsertId();
} else {
return NULL;
}
}
public function select($fieldAndTableArray, $where = NULL) {
$sql = "SELECT ";
$fieldAndTableArray;
$countTabels = count($fieldAndTableArray);//make a variable to hold the amount of colums which the user provides with the array.
/*
if the array is
array(
"tabel" => array("colum1a", "colum2a", "colum3a", "colum4a"),
"tabel2" => array("colum1b", "colum2b", "colum3b", "colum4b")
)
this would return 2 because it has 2 elements
*/
foreach($fieldAndTableArray as $table => $fields){ // cut the colums array into parts and loop threw them
$countFields = count($fields);//make a variable to hold the amount of colums which the user provides with the array.
$i =0;
foreach($fields as $field) {
$i++;
$sql .= "`{$table}`.`{$field}`";
if($i <= $countFields) {
$sql .= ", ";
}
}
}
$sql = substr($sql, 0, -2);
$sql .= " FROM ";
$i = 0;
foreach($fieldAndTableArray as $table => $fields){ // cut the colums array into parts and loop threw them
$i++;
$sql .= "`{$table}`";
if($i < $countTabels) {
$sql .=", ";
}
}
if($where != NULL) {
$sql .= " WHERE ";
foreach($where as $wherePart) {
if(is_array($wherePart)) {
$elementCounter = 0;
foreach($wherePart as $element){
$elementCounter++;
if($elementCounter >= 3){
$sql .= "?";
} else {
$sql .= $element . " ";
}
}
} else {
$sql .= " " . $wherePart . " ";
}
}
$ar = array(); //initialize an array
foreach($where as $wherePart) {
$elementCounter++;
if(is_array($wherePart)){
$elementCounter = 0;
foreach($wherePart as $value) {
$elementCounter++;
if($elementCounter == 3){
$ar[] = $this->replaceQuotesAndBackslashes($value);
}
}
}
}
}
// $this->query($query, $ar);
return $this->query($sql, $ar);
}
public function query($sql, $params) {
$query = $this->db->prepare($sql); //prepare the statement
$query->execute($params);// execute the query
return $query;
}
public function action($sql, $params) {
$query = $this->db->prepare($sql); //prepare the statement
return $query->execute($params);// execute the query
}
private function replaceQuotesAndBackslashes($fieldValue){
// $fieldValue = mysqli_real_escape_string($conn, $fieldValue);
$fieldValue = str_replace("\\", "\\\\", $fieldValue);
$fieldValue = str_replace("'", '\\\'', $fieldValue);
return $fieldValue;
}
}
/* EXAMPLES AND TESTING
Database::getInstance()->insert(
"tabelname", array(
"column1" => $value1,
"column2" => $value1
));
$result = Database::getInstance()->select(
array(
"post" => array("post_ID", "post_name", "image_ID", "message"),
"image" => array("image_path")
),
array(
array("`post`.`image_ID`", "=", "1"), "AND",
array("`post`.`post_ID`", "!=", "34567")
)
);
while ($row = $result->fetch()) {
echo"<pre>", print_r($row), "<pre />";
}
/*$sth = $db->prepare('SELECT message, post_name
FROM post
WHERE post_name < ?');
$sth->execute(array('red'));
$red = $sth->fetchAll();*/
/*
119470ef20ab9907b293fb36e5200b7c
Kevin Neven 2016 5-6 23:34*/
`

dynamic prepared insert statement

Let me preface that I just started learning prepared statements so much of this might just be to much to grasp, but I want to try.
I am trying to make a dynamic create function within my DatabaseObject class. The function would take any number of values of potentially any number of the different allowed data types. Unfortunately nothing I have tried has worked. Here is the code.
public function create() {
$db = Database::getInstance();
$mysqli = $db->getConnection();
//array of escaped values of all types in the object
$attributes = $this->sanitized_attributes();
$check = $mysqli->stmt_init();
$paramType = array();
$types = ''; $bindParam = array(); $where = ''; $count = 0;
foreach($attributes as $key=>$val)
{
$types .= 'i';
$bindParam[] = '$p'.$count.'=$param["'.$key.'"]';
$where .= "$key = ? AND ";
$count++;
}
$sql_query = "INSERT INTO `".static::$table_name."` ";
$sql_query .= "VALUES (";
foreach ($attributes as $key => $value) {
$valueType = gettype($value);
if ($valueType == 'string') {
$sql_query .= "?,";
array_push($paramType, "s");
} else if ($valueType == 'integer') {
$sql_query .= "?,";
array_push($paramType, "i");
} else if ($valueType == 'double') {
$sql_query .= "?,";
array_push($paramType, "d");
} else {
$sql_query .= "?,";
array_push($paramType, "b");
}
}
$sql_query .= ")";
}
At this point I am completely lost as to what I am suppose to do.
I have gotten simple prepared statements to work, but this one is much more complicated and dynamic and I don't know if I handled the process up to this point correctly and what to do following the sql_query in order to get this to work. All the questions here have left me confused so maybe if I got guidance with my current code to see where i went wrong it will assist.
I appreciate your time.
public function create() {
$db = Database::getInstance();
$mysqli = $db->getConnection();
$attributes = $this->sanitized_attributes();
$tableName = static::$table_name;
$columnNames = array();
$placeHolders = array();
$values = array();
foreach($attributes as $key=>$val)
{
// skip identity field
if ($key == static::$identity)
continue;
$columnNames[] = '`' . $key. '`';
$placeHolders[] = '?';
$values[] = $val;
}
$sql = "Insert into `{$tableName}` (" . join(',', $columnNames) . ") VALUES (" . join(',', $placeHolders) . ")";
$statement = $mysqli->stmt_init();
if (!$statement->prepare($sql)) {
die("Error message: " . $mysqli->error);
return;
}
$bindString = array();
$bindValues = array();
// build bind mapping (ssdib) as an array
foreach($values as $value) {
$valueType = gettype($value);
if ($valueType == 'string') {
$bindString[] = 's';
} else if ($valueType == 'integer') {
$bindString[] = 'i';
} else if ($valueType == 'double') {
$bindString[] = 'd';
} else {
$bindString[] = 'b';
}
$bindValues[] = $value;
}
// prepend the bind mapping (ssdib) to the beginning of the array
array_unshift($bindValues, join('', $bindString));
// convert the array to an array of references
$bindReferences = array();
foreach($bindValues as $k => $v) {
$bindReferences[$k] = &$bindValues[$k];
}
// call the bind_param function passing the array of referenced values
call_user_func_array(array($statement, "bind_param"), $bindReferences);
$statement->execute();
$statement->close();
return true;
}
I want to make special note that I did not find the solution myself. I had a long time developer find this solution and wanted to post it for those that might want to know.
I accidently found your old post as I was trying myself to find a solution to the exact same problem. My code seems a bit more advantagous as there is only one loop included. Therefore I will add it as a possible improvement to this post:
$sqlquery = $this->MySQLiObj->prepare($dummy);
$paramQuery = array();
$paramQuery[0] = '';
$n = count($valueArray);
for($i = 0; $i < $n; $i++) {
$checkedDataType = $this->returnDataType($valueArray[$i]);
if($checkedkDataType==false) {
return false;
}
$paramQuery[0] .= $checkedDataType;
/* with call_user_func_array, array params must be passed by reference -> & */
$paramQuery[] = &$valueArray[$i];
}
/*In array(): sqlquery(object)->bind_param(method)*/
call_user_func_array(array($sqlquery, 'bind_param'), $paramQuery);
$sqlquery->execute();
/*Can be used identical to $result = $mysqli->query()*/
$result = $this->MySQLiObj->get_result();
$sqlquery->close();
Utilizing the function returnDataType() with a switch statement, which might be faster if there is a preference for a certain data type.
private function returnDataType($input) {
switch(gettype($input)) {
case string: return 's';
case double: return 'd';
case integer: return 'i';
default: $this->LOG->doLog("Unknown datatype during database access."); return 's';
}
}

how to loop through a multi dimensional associative array the correct way

i am at the point in my script where i want to insert data into my database after looping through an associative array.
the code works so far but since i am new to programming i wish to know if there is a more efficient alternative way of doing what i am doing, since i will be adding more elseif's when my array grows, and also the fact that i am querying my database after every iteration.
foreach($database as $key=>$value) {
foreach($value as $field => $cell){
if ($field =='itemid') {
echo "the item id is $cell";
$col1 = $cell ;
}
elseif ($field =='title') {
echo "the title is $cell";
$col2 = $cell;
}
elseif ($field =='starttime') {
echo "the start time is $cell";
$col3 = $cell;
}
}
$query = "INSERT INTO cordless_drill(itemid,title,starttime) VALUES ('$col1','$col2','$col3')";
mysqli_query($dbc,$query);
}
// here is a code snippet
// $db = new MyDbClass();
// $db->insert->('cordless_drill', $cell); // where $cell is holding key/value pairs
public function insert($table, $obj) {
return $this->query("INSERT INTO ".$table.$this->obj2KeyValue($obj));
}
private function obj2KeyValue($obj) {
$i = count($obj);
$k = ""; $v = "";
$init = false;
$sql = " SET ";
while (list($k, $v) = each($obj)) {
if ($v != "") {
$v = $this->mysqli->real_escape_string($v);
if ($init) $sql .= ", ";
else $init = true;
$sql .= $k.'="'.$v.'"';
}
}
return $sql;
}
public function query($q) {
if ($this->debug) {
$logFile = "sql_query.log";
$handle = fopen($logFile, "a+");
$data = $q."\n";
fwrite($handle, $data);
fclose($handle);
}
return $this->mysqli->query($q);
}

prepared statements - creating a single method*

FYI. ended up going with PDO solution as this was simpler.
I'm trying to add a single method to handle all queries to the database. I want the queries to use parameter binding. How do I handle a variable amount of function parameters in mysqli_stmt_bind_param()?
This post here led me to understand the pros of parameter binding.
Here is my example code..where I am currently stuck at is marked.
INPUT PARAMETERS
$query = "INSERT INTO b0 VALUES (?, ?, ?)"
$par_arr = {'bookmark', 'http://www.bookmark.com', 'tag'}
PROTOTYPE CODE
protected static function query($query, $par_arr)
{
if($statement=mysqli_prepare(one::$db, $query)
{
mysqli_stmt_bind_param($statement, "s", ...variable amount of parameters...);<----how should this be handled?
...
Update 2: If you experience any further problems with this code, then you should probably follow this advice and use PDO instead.
This is how you should be using call_user_func_array [docs]:
protected static function query($query, $types, $values) {
if($statement = mysqli_prepare(one::$db, $query) {
$parameters = array_merge(array($statement, $types), $values);
call_user_func_array('mysqli_stmt_bind_param', $parameters);
// ...
}
}
where $types is a string indicating the type of each value, as described in the mysqli_stmt_bind_param documentation (call_user_func_array is even mentioned there).
Update: It seems it is not that easy after all, and you have to create references to the values first:
foreach($values as $k => $v) {
$values[$k] = &$v;
}
$parameters = array_merge(array($statement, $types), $values);
call_user_func_array('mysqli_stmt_bind_param', $parameters);
// ...
call_user_func_array is for user defined functions per php.net
No it's not. The first parameter is of type callback, and the documentation says (emphasis mine):
A PHP function is passed by its name as a string. Any built-in or user-defined function can be used, except language constructs such as: array(), echo(), empty(), eval(), exit(), isset(), list(), print() or unset().
Next remark:
is just used to simplify syntax for passing arrays to user defined functions
Have you had a look at the examples? Each element of the array you pass to call_user_func_array will be passed as argument to the function you specify. Arrays are the only way to have a collection of values of variable size.
Because i find prepared statements boring, I am processing placeholders manually, and experience not a single problem of yours
private function prepareQuery($args)
{
$raw = $query = array_shift($args);
preg_match_all('~(\?[a-z?])~',$query,$m,PREG_OFFSET_CAPTURE);
$pholders = $m[1];
$count = 0;
foreach ($pholders as $i => $p)
{
if ($p[0] != '??')
{
$count++;
}
}
if ( $count != count($args) )
{
throw new E_DB_MySQL_parser("Number of args (".count($args).") doesn't match number of placeholders ($count) in [$raw]");
}
$shift = 0;
$qmarks = 0;
foreach ($pholders as $i => $p)
{
$pholder = $p[0];
$offset = $p[1] + $shift;
if ($pholder != '??')
{
$value = $args[$i-$qmarks];
}
switch ($pholder)
{
case '?n':
$value = $this->escapeIdent($value);
break;
case '?s':
$value = $this->escapeString($value);
break;
case '?i':
$value = $this->escapeInt($value);
break;
case '?a':
$value = $this->createIN($value);
break;
case '?u':
$value = $this->createSET($value);
break;
case '??':
$value = '?';
$qmarks++;
break;
default:
throw new E_DB_MySQL_parser("Unknown placeholder type ($pholder) in [$raw]");
}
$query = substr_replace($query,$value,$offset,2);
$shift+= strlen($value) - strlen($pholder);
}
$this->lastquery = $query;
return $query;
}
and thus an insert query can be called as simple as
$db->run("INSERT INTO table SET ?u",$data);
I have added the complete code to create a single method for select prepared statement and insert prepared statement, Please follow the instruction and read all the comments.
create database with the name 'test' and add the following query to create "users" table in the
CREATE TABLE IF NOT EXISTS `users` (
`users_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`first_name` varchar(100) NOT NULL,
`last_name` varchar(100) NOT NULL,
PRIMARY KEY (`users_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=10 ;
INSERT INTO `users` (`users_id`, `first_name`, `last_name`) VALUES
(1, 'daniel', 'martin'),
(2, 'daniel', 'martin');
<?php
error_reporting(E_ALL);
ini_set('display_errors',1);
session_start();
class mysqli_access extends mysqli{
private $ip1;
private $dbconn;
private $hostname = HST; // hostname
private $username = USR; // username
private $password = PWD; // password
private $dbname = DBN; // datbase name
function mysqli_access()
{
$ip= $_SERVER['REMOTE_ADDR'];
$ip1="ip_".str_replace('.', "", $ip);
if(!is_resource($_SESSION[$ip1]))
{
$this->dbconn = new mysqli($this->hostname,$this->username,$this->password,$this->dbname);
$_SESSION[$ip1] = $this->dbconn;
$dbconn = $this->dbconn;
if( $this->connect_error ) {
$this->Display_error('', $this->connect_errno, $this->connect_error, __FUNCTION__);
}
}
else {
$this->dbconn = $_SESSION[$ip1]; // success
}
return $this->dbconn;
}
function SelectPrepared($sql,$types,$params,$rows = '')
{
$results = array();
if ($stmt = $this->dbconn->prepare($sql)) {
if($types&&$params)
{
$bind_names[] = $types;
for ($i=0; $i<count($params);$i++)
{
$bind_name = 'bind' . $i;
$$bind_name = $params[$i];
$bind_names[] = &$$bind_name;
}
$return = call_user_func_array(array($stmt,'bind_param'),$bind_names);
}
$stmt->execute(); /* execute query */
$meta = $stmt->result_metadata();
while ($field = $meta->fetch_field()) {
$var = $field->name;
$$var = null;
$fields_arr[$var] = &$$var;
}
call_user_func_array(array($stmt,'bind_result'),$fields_arr);
if($rows == 1){
while ($stmt->fetch()) {
$results = array();
foreach($fields_arr as $k => $v)
$results[$k] = $v;
}
}else{
$i = 0;
while ($stmt->fetch()) {
$results[$i] = array();
foreach($fields_arr as $k => $v)
$results[$i][$k] = $v;
$i++;
}
}
return $results;
}
}
public function InsertPrepared($tblName,$arrFieldNameValue,$replace_flag=0){
$TableName = $tblName;
if($replace_flag==0)
{
$sqlFirst ="INSERT INTO " . $TableName . "(";
}
if($replace_flag==1)
{
$sqlFirst ="INSERT IGNORE INTO " . $TableName . "(";
}
if($replace_flag==2)
{
$sqlFirst ="REPLACE INTO " . $TableName . "(";
}
$sqlSecond =" values(";
$params = array();
$types = '';
while(list($key,$value) = each($arrFieldNameValue))
{
$sqlFirst = $sqlFirst . $key . ",";
$sqlSecond = $sqlSecond . '?' . ",";
$params[] = $value;
$types = $types . $this->GetValType($value);
}
$sqlFirst = substr($sqlFirst,0,strlen($sqlFirst)-1) . ") ";
$sqlSecond = substr($sqlSecond,0,strlen($sqlSecond)-1) .")";
$sql = $sqlFirst . $sqlSecond;
if ($stmt = $this->dbconn->prepare($sql)) {
if($types&&$params)
{
$bind_names[] = $types;
for ($i=0; $i<count($params);$i++)
{
$bind_name = 'bind' . $i;
$$bind_name = $params[$i];
$bind_names[] = &$$bind_name;
}
$return = call_user_func_array(array($stmt,'bind_param'),$bind_names);
}
$stmt->execute(); /* execute query */
}
return mysqli_insert_id($this->dbconn);
}
private function GetValType($Item)
{
switch (gettype($Item)) {
case 'NULL':
case 'string':
return 's';
break;
case 'integer':
return 'i';
break;
case 'blob':
return 'b';
break;
case 'double':
return 'd';
break;
}
return 's';
}
}
class Model_NAME extends mysqli_access
{
function Model_NAME() {
$this->tablename = TABLENAME;
$this->mysqli_access();
}
##---------------------------- Custom function start from here -----------------#
## fetch settings values
function getUserRow($id,$key) {
$sql ="SELECT first_name,last_name FROM ".$this->tablename." WHERE first_name=? and users_id = ?";
$param = "si";
$array_of_params[] = addslashes($key);
$array_of_params[] = addslashes($id);
$result= $this->SelectPrepared($sql,$param,$array_of_params,1);
//last parameter 1 use if want fetch single row , other wise function will return multi dimensional array
return $result;
}
## fetch settings values
function getUserRows($last_name) {
$sql ="SELECT first_name,last_name FROM ".$this->tablename." WHERE last_name= ?";
$param = "s";
$array_of_params[] = addslashes($last_name);
$result= $this->SelectPrepared($sql,$param,$array_of_params);
//last parameter 1 use if want fetch single row , other wise function will return multi dimensional array
return $result;
}
function addValue($Array) {
return $this->InsertPrepared( $this->tablename , $Array);
}
}
// configuration
define('HST','localhost');
define('USR','root');
define('PWD','techmodi');
define('DBN','test');
define('TABLENAME','users');
$obj = new Model_NAME();
$arr = array();
$arr['first_name'] = addslashes("daniel");
$arr['last_name'] = addslashes("martin");
$obj->addValue($arr); // for insert records
// after inserting get the records
$singleRow = $obj->getUserRow(1,'daniel'); // for select single records
$multiRow =$obj->getUserRows('martin'); // for select records
echo '<pre>';
echo '<br/>-------- Single Records -----------------<br/>';
print_r($singleRow);
echo '<br/>-------- Multiple Records-----------------<br/>';
print_r($multiRow);
?>

Categories