I have a prepared statement function for INSERT, I got this function in this forum. but I don't know how to pass variables/array to this function. I am new at this, some help would be really useful.
I want somehing like this:
$obj->insert_data($parameter)
I have listed the function below..
function insert_datas($array) {
$placeholders = array_fill(0, count($array), '?');
$keys = $values = array();
foreach($array as $k => $v) {
$keys[] = $k;
$values[] = !empty($v) ? $v : null;
}
$stmt = self::$mysqli->stmt_init();
$query = 'INSERT INTO `'.DB_TABLE_PAGES.'` '.
'('.implode(',', $keys).') VALUES '.
'('.implode(',', $placeholders).')';
$stmt->prepare($query);
call_user_func_array(
array($stmt, 'bind_param'),
array_merge(
array(str_repeat('s', count($values))),
$values
)
);
$stmt->execute();
}
Try this, hope this helps!
define('DB_HOST', 'database_host');
define('DB_NAME', 'database_name');
define('DB_USER', 'database_user');
define('DB_PASS', 'database_password');
$dbc = new PDO('mysql:host='. DB_HOST .';dbname='. DB_NAME, DB_USER, DB_PASS);
function insert_datas($array) {
foreach($array as $a) {
$insert_table = "INSERT INTO table (column) VALUES (:column)";
$stmt = $dbc->prepare($insert_table);
$stmt->bindValue(':column', $a['key'], PDO::PARAM_STR);
$stmt->execute();
}
}
Related
I'm trying to bind my values into a prepared statement in PDO.
Here is the pre requisite codes that that uses the prepared statement block:
$tab = 'air_user';
$fie = array('USER_NAME', 'USER_PASSWORD' , 'USER_EMAIL');
$name = $_POST['name'];
$pass = $_POST['password'];
$email = $_POST['email'];
$val = array(
'name' => $name,
'pass' => $pass,
'email' => $email
);
$this->connect($tab,$fie,$val);
And here is the part wherein I prepare those values and make the necessaru insertions:
public function connect($table,$fields,$values)
{
try{
$con = new PDO ('mysql:host=localhost;dbname=air','root','123456');
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$con->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$fields = implode(", ", $fields);
echo $fields;
$values = implode(", ", $values);
echo $values;
// have to make this prevent sql injection //
$stmt = $con->prepare("INSERT INTO $table(ID,$fields) VALUES (?,?,?,?)");
$stmt->execute(array('',$values));
} catch(PDOException $e) {
die("this cant connect the database");
}
}
so why isit my INSERT not Working ? isit can anyone help me take a look of it , i tryed so many things , none of them work.
No, don't implode the values that your going to pass inside the ->execute(), it must be an array:
$fields = implode(", ", $fields);
// $values = implode(", ", $values); // DONT IMPLODE!
$values = array_values($values);
$stmt = $con->prepare("INSERT INTO $table(ID,$fields) VALUES (NULL, ?,?,?)");
$stmt->execute($values);
Or #Augwa's suggestion:
// $fields = implode(", ", $fields); // not needed
// $values = implode(", ", $values); // DONT IMPLODE!
$placeholders = substr(str_repeat('?,', sizeOf($fields)), 0, -1);
// $placeholders = implode(', ', array_fill(0, count($values), '?'));
$stmt = $con->prepare(
sprintf(
"INSERT INTO %s (%s) VALUES (%s)",
$table,
implode(',', $fields),
$placeholders
)
);
$stmt->execute($values);
Lets say I have this code:
$array = array('one' => $one, 'two' => $two);
$sql->sql_insert('table_name', $array);
I have the class object $sql and the function sql_insert but how would I use the mysqli prepared statements to bind the values and insert it into the db? And lets say the mysqli connection is $this->connection
Any advice would be great thanks.
edited:
function sql_insert_bind($table, $insert){
$count = count($insert);
$bind_val = '';
for($i = 0; $i <= $count; $i++){
$bind_val .= '?, ';
}
$query = $this->connection->prepare('INSERT INTO `'.$table.'` VALUES ('.substr($bind_val, 0, -2).')');
foreach($insert as $key => $value){
$query->bind_param($key, $value);
}
$query->execute();
}
I get the error message: Fatal error: Call to a member function bind_param() on a non-object but $this->connection is the mysqli object
Ok, here's how I would approach this with PDO (since OP asked)
I'll assume you've instantiated or injected a PDO object into your class as the $connection property, eg
class SQLClass {
/**
* #var PDO
*/
private $connection;
public function __construct(PDO $pdo) {
$this->connection = $pdo;
}
// etc
}
$pdo = new PDO('mysql:host=localhost;dbname=db_name;charset=utf8', 'username', 'password', array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC));
$sql = new SQLClass($pdo);
Then, in your sql_insert_bind method
$keys = array_keys($insert);
$cols = array_map(function($key) {
return sprintf('`%s`', $key);
}, $keys);
$placeholders = array_map(function($key) {
return sprintf(':%s', $key);
}, $keys);
$params = array_combine($placeholders, $insert);
$query = sprintf('INSERT INTO `%s` (%s) VALUES (%s)',
$table, implode(',', $cols), implode(',', $placeholders));
$stmt = $this->connection->prepare($query);
$stmt->execute($params);
You should bind each variable seperately, bind_param will accept many variables to bind:
$array = array('one' => $one, 'two' => $two);
$query = $sql->prepare("INSERT INTO `table` VALUES (?, ?)");
$query->bind_param('ss', $array['one'], $array['two']);
$query->execute();
// inserted
I am trying to use staticsan´s answer in this question for prepared statements.
Lets take this example:
$stmt = $mysqli->prepare("INSERT INTO something (userid, time, title) VALUES (?, ?, ?)");
$stmt->bind_param('iis', $userid, time(), $title);
$stmt->execute();
In staticsan´s answer imploding the array is adding all the values into the mysql statement so that in the end we can insert multiple data into the database with just one statement.
How would this be done in my example?
This is completely valid:
$stmt = $mysqli->prepare("INSERT INTO something (userid, time, title) VALUES (?, ?, ?)");
$stmt->bind_param('iis', $userid, time(), $title);
$stmt->execute();
$stmt->bind_param('iis', $userid, time(), $title);
$stmt->execute();
$stmt->bind_param('iis', $userid, time(), $title);
$stmt->execute();
$stmt->bind_param('iis', $userid, time(), $title);
$stmt->execute();
You can foreach over your array of values to insert and bind and execute each time. It wont be quite as fast as the bulk insert in the example you linked, but it will be more secure.
You can build prepared statement using code as mentioned here,
PDO Prepared Inserts multiple rows in single query
PHP logic will be sort of like,
/**
* Insert With Ignore duplicates in Mysql DB.
*/
public static function insertWithIgnore($em, $container, $tableName, $fields, $rows)
{
$query = "INSERT IGNORE INTO $tableName (`" . implode('`,`', $fields) . "`) VALUES ";
$placeHolr = array_fill(0, count($fields), "?");
$qPart = array_fill(0, count($rows), "(" . implode(',', $placeHolr) . ")");
$query .= implode(",", $qPart);
$pdo = self::getPDOFromEm($em, $container);
$stmt = $pdo->prepare($query);
$i = 1;
foreach ($rows as $row) {
$row['created_at'] = date("Y-m-d H:i:s");
foreach ($fields as $f) {
if (!isset($row[$f])) {
$row[$f] = null;
}
$stmt->bindValue($i++, $row[$f]);
}
}
$result = $stmt->execute();
if ($result == false) {
$str = print_r($stmt->errorInfo(), true);
throw new \Exception($str);
}
$stmt->closeCursor();
$pdo = null;
}
/**
* Replace old rows in Mysql DB.
*/
public static function replace($em, $container, $tableName, $fields, $rows, $extraFieldValues = null)
{
if ($extraFieldValues != null) {
$fields = array_unique(array_merge($fields, array_keys($extraFieldValues)));
}
$query = "REPLACE INTO $tableName (`" . implode('`,`', $fields) . "`) VALUES ";
$placeHolr = array_fill(0, count($fields), "?");
$qPart = array_fill(0, count($rows), "(" . implode(',', $placeHolr) . ")");
$query .= implode(",", $qPart);
$pdo = self::getPDOFromEm($em, $container);
$stmt = $pdo->prepare($query);
$i = 1;
foreach ($rows as $row) {
if ($extraFieldValues != null) {
$row = array_merge($row, $extraFieldValues);
}
foreach ($fields as $f) {
$stmt->bindValue($i++, $row[$f]);
}
}
$stmt->execute();
if (!$stmt) {
throw new \Exception("PDO::errorInfo():" . print_r($stmt->errorInfo(), true));
}
$stmt->closeCursor();
$pdo = null;
}
I'm not sure if the issue is with the prepare() statement itself or with the bindValues, but I cannot figure out why this works as a query() and not as a prepared statement.
$dbh = new PDO("mysql:host=$dbhost", $dbuser, $dbpass, $options);
$dbh->beginTransaction();
$record_data = $dbh->prepare("UPDATE $db.$dbt SET :column = :value WHERE `key` = :key;");
foreach ( $qaPairs as $pair ) {
list($question , $answer) = explode('=', $pair);
echo "$key : $question $answer";
$record_data->bindValue(':column', $question);
$record_data->bindValue(':value', $answer);
$record_data->bindValue(':key', $key);
$record_data->execute();
}
$dbh->commit();
If I replace the $record_data->bindValue…s and the $record_data->execute() with
$dbh->query("UPDATE `$db`.`$dbt` SET `$question`='$answer' WHERE `key`='$key';");
it works.
For troubleshooting, I added the echo statement, and the values printed are just letters and digits and no quoting; also, the database and table names are not quoted/tick'd.
I read in another question that looping causes problems with prepare and bind_. I switched from bindParam to bindValue, but that didn't seem to help…
EDIT: results of var_dump($key,$question,$answer):
string(17) "m3dc78db1e8368428" string(3) "age" string(2) "23" age 23
You cannot bind a table field name. As much as you cannot bind a table name. You'll have to use this code instead:
$dbh = new PDO("mysql:host=$dbhost", $dbuser, $dbpass, $options);
$dbh->beginTransaction();
foreach ( $qaPairs as $pair ) {
list($question , $answer) = explode('=', $pair);
// Initialize $column here… remember to sanitize it!!!
$record_data = $dbh->prepare("UPDATE $db.$dbt SET $question = :value WHERE `key` = :key;");
echo "$key : $question $answer";
$record_data->bindValue(':value', $answer);
$record_data->bindValue(':key', $key);
$record_data->execute();
}
$dbh->commit();
Reference:
Comment on PHP pdo.prepare.php
Did you change the error mode to 'exception' and used try/catch to display possible errors?
Here is how you do it:
<?php
$dbh = new PDO("mysql:host=$dbhost", $dbuser, $dbpass, $options);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
try {
$dbh->beginTransaction();
$record_data = $dbh->prepare("UPDATE $db.$dbt SET :column = :value WHERE `key` = :key;");
foreach ( $qaPairs as $pair ) {
list($question , $answer) = explode('=', $pair);
echo "$key : $question $answer";
$record_data->bindParam(':column', $question);
$record_data->bindParam(':value', $answer);
$record_data->bindParam(':key', $key);
$record_data->execute();
}
$dbh->commit();
} catch(PDOException $e) {
echo $e;
}
?>
I hope this step provides you with more insight.
Furthermore you need to use bindParam(), because the values of the variables are changing on each iteration.
final code:
error_reporting(-1);
$dbh = new PDO("mysql:host=$dbhost", $dbuser, $dbpass, $options);
$dbh->beginTransaction();
foreach ( $qaPairs as $pair ) {
list($question , $answer) = explode('=', $pair);
//var_dump($key,$question,$answer);
try {
$record_data = $dbh->prepare("UPDATE $db.$dbt SET $question = :value WHERE `key` = :key;");
//$record_data->bindParam(':column', $question);
$record_data->bindParam(':value', $answer);
$record_data->bindParam(':key', $key);
//$dbh->query("UPDATE `$db`.`$dbt` SET `$question`='$answer' WHERE `key`='$key';");
//$record_data->execute(array(1=>$question,2=>$answer,3=>$key));
//$record_data->execute(array(':column'=>$question,':value'=>$answer,':key'=>$key));
$record_data->execute();
}
catch(PDOException $e) {
echo $e;
}
}
I have the following script:
<?php
$mysqli = new mysqli('localhost', 'user', 'password', 'database');
$statement = $mysqli->stmt_init();
$query = 'SELECT * FROM table WHERE id = ? AND active = 1';
$statement->prepare($query);
$parameters = array('i');
$inputParameters = array(10);
foreach ($inputParameters as $param) {
$parameters[] =& $param;
}
call_user_func_array(array($statement, 'bind_param'), $parameters);
$statement->execute();
$statement->store_result();
echo $statement->num_rows;
?>
Which returns exactly the right number of rows.
But when I change the script to:
<?php
$mysqli = new mysqli('localhost', 'user', 'password', 'database');
$statement = $mysqli->stmt_init();
$query = 'SELECT * FROM table WHERE id = ? AND active = ?';
$statement->prepare($query);
$parameters = array('ii');
$inputParameters = array(10, 1);
foreach ($inputParameters as $param) {
$parameters[] =& $param;
}
call_user_func_array(array($statement, 'bind_param'), $parameters);
$statement->execute();
$statement->store_result();
echo $statement->num_rows;
?>
It returns 0. Does anyone have an explanation for that? To me it looks like num_rows stops working as soon as you have more than 1 param bound to the statement.
p.s: in the full script there's a reason to use call_user_func_array here, not using call_user_func_array gives the same result.
I found the answer after a lot of debugging: $parameters will be array('ii', 1, 1) in the second code. This is because of the reference used there. Changing foreach ($inputParameters as $param) { to foreach ($inputParameters as &$param) { fixed the problem