PHP/MySQL: Dynamic prepared statement with insert/update query - php

I found this http://net.tutsplus.com/tutorials/php/the-problem-with-phps-prepared-statements/
and it works really good to have it in a seperate php file which my other files calls to with a query as argument.
Is it possible to make something similar with other queries like insert and update?

This is the updated example:
$params is an array.
function insertToDB($params, $db) { //Pass array and db
$fields = array();
$conn = new mysqli('localhost', 'root', 'root', 'db') or die('XXX');
$stmt = $conn->stmt_init();
$stmt->prepare("SELECT * FROM ".$db);
$stmt->execute();
$meta = $stmt->result_metadata();
while ($field = $meta->fetch_field()) {
$fields[] = $field->name;
}
$fields = implode(", ", $fields);
$placeholders = implode(',', array_fill(0, count($params), '?'));
$types = '';
foreach($params as $value) {
$types.= substr(strtolower(gettype($value)), 0, 1);
}
$ins = "INSERT INTO MYDB (".$fields.") VALUES (".$placeholders.")";
$bind_names[] = $types;
for ($i = 0; $i < count($params); $i++) {
$bind_name = 'bind' . $i;
$$bind_name = $params[$i];
$bind_names[] = &$$bind_name;
}
if ($stmt->prepare($ins)) {
call_user_func_array(array($stmt,'bind_param'),$bind_names);
$insresult = $stmt->execute();
}
return $insresult;
$stmt->close();
}

Related

PDO Insert multiple rows into MySQL a table

I am trying to insert multiple lines in a single query based on this example:
[a link][1]: http://thisinterestsme.com/pdo-prepared-multi-inserts/
But the values are not inserted.
$pdo = new PDO("mysql:host=$this->host;dbname=$this->database", $this->login,
$this->password);
$columnNames = array_keys($dataVals[0]);
unset($columnNames["8"]);
unset($columnNames["9"]);
foreach ($dataVals as $arrayIndex => $row) {
$params = array();
foreach ($row as $columnName => $columnValue) {
$param = ":".$columnName.$arrayIndex;
$params[] = $param;
$toBind[$param] = $columnValue;
}
$rowsSQL[] = "(".implode(", ", $params).")";
}
$sql = "INSERT INTO `$this->table` (".implode(", ", $columnNames).") VALUES ".implode(", ", $rowsSQL);
$pdoStatement = $pdo->prepare($sql);
foreach ($toBind as $param => $val) {
$pdoStatement->bindParam($param, $val);
}
$pdoStatement->execute();

mysqli_prepare query returning false

I am attempting to bind params to a sql statement using call_user_func_array as describe on Dynamically Bind Params in Prepared Statements with MySQLi; however, my mysqli_prepare keeps returning false.
Here is my data function that is called to store data:
function storeData($form_data, $table_name, $cxn){
if(!is_array($form_data)){
return false;
exit();
}
$types = str_repeat("s", count($form_data));
$params = array();
$params[] = &$types;
$keys = array_keys($form_data);
$values = array_values($form_data);
for ($i = 0; $i < count($values); $i++) {
$params[] = &$values[$i];
}
$sql = "INSERT INTO $table_name (" . implode(',', $keys) . ") VALUES (" .
implode(',', array_fill(0, count($values), '?')) . ")
ON DUPLICATE KEY UPDATE ";
$updates = implode(',', array_map(function($col) {
return "$col = VALUES($col)";
}, $keys));
$sql .= $updates;
if($stmt = mysqli_prepare($cxn, $sql)){
call_user_func_array(array($stmt, 'bind_param'), $params);
return mysqli_stmt_execute($stmt);
}
Here is my $sql string at time of prepare:
$sql"INSERT INTO interest (Baseball,Basketball,Camping,Canoeing,Cycling,Football,Gaming,Golf,Hiking,Parks,Photography,Runway,Skydiving,Soccer,Username) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) ON DUPLICATE KEY UPDATE Baseball = VALUES(Baseball),Basketball = VALUES(Basketball),Camping = VALUES(Camping),Canoeing = VALUES(Canoeing),Cycling = VALUES(Cycling),Football = VALUES(Football),Gaming = VALUES(Gaming),Golf = VALUES(Golf),Hiking = VALUES(Hiking),Parks = VALUES(Parks),Photography = VALUES(Photography),Runway = VALUES(Runway),Skydiving = VALUES(Skydiving),Soccer = VALUES(Soccer),Username = VALUES(Username)"
Here is my $params and $key outputs:
$keysarray[15]
$keys[0]"Baseball"
$keys[1]"Basketball"
$keys[2]"Camping"
$keys[3]"Canoeing"
$keys[4]"Cycling"
$keys[5]"Football"
$keys[6]"Gaming"
$keys[7]"Golf"
$keys[8]"Hiking"
$keys[9]"Parks"
$keys[10]"Photography"
$keys[11]"Runway"
$keys[12]"Skydiving"
$keys[13]"Soccer"
$keys[14]"Username"
$paramsarray[16]
$params[0]"sssssssssssssss"
$params[1]"0"
$params[2]"0"
$params[3]"0"
$params[4]"0"
$params[5]"0"
$params[6]"0"
$params[7]"0"
$params[8]"0"
$params[9]"0"
$params[10]"0"
$params[11]"0"
$params[12]"0"
$params[13]"0"
$params[14]"0"
$params[15]"test0613"
$valuesarray[15]
$values[0]"0"
$values[1]"0"
$values[2]"0"
$values[3]"0"
$values[4]"0"
$values[5]"0"
$values[6]"0"
$values[7]"0"
$values[8]"0"
$values[9]"0"
$values[10]"0"
$values[11]"0"
$values[12]"0"
$values[13]"0"
$values[14]"test0613"
There error existed in a column i was attempting to map which did not exist. The error procedure was found here, which allowed me to produce fatal errors that noted a column did not exist in the table I was referencing.

Passing array through bind_param

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

Bind Variable Amount of Parameters in Prepared Statement

I'm currently trying to build a little generic function to make inserts. My goal is to pass the table, the columns, values and types to fullfill an insert.
My only problem is the statement:
$stmt -> bind_param($types, $var1, $var2 ...);
What i would basically need is something like this:
$stmt -> bind_param($types, $array);
This is what i got till now:
function insert($into, $columns, $values, $types) {
global $connection;
// Check Correct Length
if(count($columns) != count($values) ||
count($columns) != count($types)) {
return false;
}
$count = count($columns);
$column_string = "";
$value_string = "";
$value_types = "";
for($i = 0; $i < $count; $i++) {
$column_string .= $columns[$i];
$value_types .= $types[$i];
$value_string .= '?';
if($i + 1 < $count) {
$column_string .= ',';
$value_string .= ',';
}
}
$sql = "INSERT INTO $into ($column_string) VALUES ($value_string)";
// Execute Statement
if($stmt = $connection -> prepare($sql)) {
// $stmt -> bind_param("sss", $transaction, $email, $status);
// What to do here?
$stmt -> execute();
$stmt -> close();
}
The SQL statement already looks fine. Also the types are ready - i just need a way to dynamically bind the parameters...
Well I assume, that in $columns is defined as $columns = array('col1', 'col2'/*...*/); and $values as $values = array($val1, $val2/*...*/);
I would create function for column names escaping.
$escapeCols = function($column) {
return sprintf('%s', $column);
};
Another function for creating ? placeholders
$placeholders = function ($values) {
return array_fill(0, count($values), '?');
}
You can than prepare query
$sql = sprintf(
'INSERT INTO %s (%s) VALUES (%s)',
$table,
implode(', ', array_map($escapeCols, $columns),
implode(', ', $placeholders($values))
);
And then you can call execute
$stmt = $connection->prepare($sql);
$stmt->execute($values);
This way can be easily transformed if you would have $values defined as
$values = array('col1' => $va1, 'col2' => $val2);

PDO bind loop index

I have some user uploaded images that can be sorted and need to save the image position. Was thinking that I could do this easy enough by just using the loop index while iterating through them. However using my $i variable to bind the 3rd param is being passed as a reference and I need the value. How do I get around this?
Here's the code:
$postId = $args['postId'];
$images = explode(",", $args['images']);
$sql = 'INSERT INTO post_image (name,postId,ordinal) VALUES ';
$part = array_fill(0, count($images), "(?, ?, ?)");
$sql .= implode(",", $part);
logit($sql);
try{
$db = DB::getInstance();
$stmt = $db->dbh->prepare($sql);
$count = count($images);
$n = 1;
for($i = 0; $i < $count; $i++){
$stmt->bindParam($n++, $images[$i]);
$stmt->bindParam($n++, $postId);
$stmt->bindParam($n++, $i);
}
$result = $stmt->execute();
if($result !== false) {
return true;
}else {
logit('Query Failed');
return false;
}
}catch(PDOException $e) {
logit($e->getMessage());
return false;
}
I fixed it by using bindValue for the third param.

Categories