I have an array, which includes an insertId (as a key) several other values; this needs to be submitted as a $key=> $value array (e.g. 1 => 2, 1 =>3, 1=>5) etc.
However, when I bind the parameters within the foreach loop, I keep getting an array to string conversion error. as a result I get one row being inserted into the db (the correct key,and then a 0).
function instructorSubject()
{
$query = "INSERT into instructor_has_subject
SET instructor_id = :instructor_id,
subject_id = :id";
$last_id = $this->conn->lastInsertId();
$stmt = $this->conn->prepare($query);
//print_r($last_id);
//print_r($this->id);
if (isset($this->id) && $this->id != '') {
foreach ($_POST as $values) {
$stmt->bindParam(":instructor_id", $last_id, PDO::PARAM_INT);
$stmt->bindParam(":id", $this->id, PDO::PARAM_INT);
}
if($stmt->execute())
{
return true;
}
else
{
var_dump($stmt);
print_r($stmt->errorInfo());
return false;
}
}
}
A sample array is something like this:
the insert id: 87
and then the second array appearing as a straight forward key=>value pair (for example:)
( [0] => 1 [1] => 3 )
I feel it has something to do with where I'm binding within the foreach. thanks in advance for any assistance.
After speaking to you in chat, this is the solution we came up with.
function instructorSubject()
{
$query = "INSERT INTO instructor_has_subject (instructor_id, subject_id) VALUES (?,?)";
$last_id = $this->conn->lastInsertId();
$stmt = $this->conn->prepare($query);
if(!empty($this->id)) {
foreach($_POST['subject_id'] as $id) {
$stmt->execute(array(
$last_id,
$id
));
}
}
}
The main thing we changed I believe was changing $_POST to $_POST['subject_id'].
We also removed bindParam completely from the function, instead opting for unnamed parameters and passing the variables via execute() inside the loop.
Related
I'm having trouble with a PDO insert.
I'd like to insert a multidimensional array into a db, which i managed to.
However, i also would like to insert a completely different array, disconnected from the first one into the same db line (which means same INSERT query).
1st multidimensional array = $_POST['training']
2nd array = $training_diploma
Kinda difficult to explain. Here is the code :
$id = "1";
$training_diploma = ("master", "bachelor");
$id_training_key = $id_training_key = $id.'_'.$training_diploma; (return: 1_master)
$sql = "INSERT INTO users_resumes (id,resume_category,id_training_key,training_diploma,training_school,training_level,training_start_date,training_end_date) VALUES ($id,'Training',$id_training_key,:training_diploma,:training_school,:training_level,:training_start_date,:training_end_date)";
$stmt= $pdo->prepare($sql);
foreach($_POST['training'] as $params){
$stmt->execute($params);
}
Any help is very welcome !!! Thx a looot !
You need to iterate the $training_diploma array as well as the $_POST array. It would be better to also include the id and id_training_key as parameters in your query so you don't have to prepare a new query for each set of values:
$id = "1";
$training_diploma = array("master", "bachelor");
$sql = "INSERT INTO users_resumes (id,resume_category,id_training_key,training_diploma,training_school,training_level,training_start_date,training_end_date) VALUES (:id,'Training',:id_training_key,:training_diploma,:training_school,:training_level,:training_start_date,:training_end_date)";
$stmt= $pdo->prepare($sql);
foreach($_POST['training'] as $params) {
foreach ($training_diploma as $diploma) {
$stmt->execute(array_merge($params, array('id' => $id, 'id_training_key' => $id . '_' . $diploma)));
}
}
So I have a spaghetti PHP app I am converting to using OOP database class / MVC layout
Previously, on a form, there was a sql statement being executed on post that would fetch the inserted ID into a bind variable (based on the SO Get the auto-generated ID after an insert
$sql ="insert into table (name, type) values (:name, :type) returning id into :id";
$squery = oci_parse($link, $sql);
oci_bind_by_name($squery,":name", $_POST['name']);
oci_bind_by_name($squery,":type", $_POST['type']);
oci_bind_by_name($squery,":id", $id,-1, SQLT_INT);
oci_execute($squery);
at this point, $id could be used as the variable has been assigned the inserted id
So, here is my issue, my model passes the values from the $_POST to the database class, but never assigns the variable
Model
function create(){
$sql ="insert into table (name, type) values (:name, :type) returning id into :id";
$this->db->execute($sql, "table insert",
array(
array(":name", $_POST['name'], -1, SQLT_CHR),
array(":type", $_POST['type'], -1, SQLT_CHR),
array(":id", $id,-1, SQLT_INT)
)
);
return $id;
}
Database Class( based on http://docs.oracle.com/cd/E17781_01/appdev.112/e18555/ch_three_db_access_class.htm )
public function execute($sql, $action, $bindvars = array()) {
$this->stid = oci_parse($this->conn, $sql);
if ($this->prefetch >= 0) {
oci_set_prefetch($this->stid, $this->prefetch);
}
foreach ($bindvars as $bv) {
// oci_bind_by_name(resource, bv_name, php_variable, length , type)
oci_bind_by_name($this->stid, $bv[0], $bv[1], $bv[2], $bv[3]);
}
oci_set_action($this->conn, $action);
oci_execute($this->stid); // will auto commit
}
The class is correct, meaning it will execute fine , it just will not return the last inserted id.
this is what i came up with (surely theres a better answer)
the issue was when i passed in the variable for returning into bind, it was not passing the variable as a variable ($id) it was passing it in as a variable value, and it hadnt been assigned so it was blank
so in my database class i created
public function executeAndReturnID($sql, $action, $bindvars = array(), $return) {
$this->stid = oci_parse($this->conn, $sql);
if ($this->prefetch >= 0) {
oci_set_prefetch($this->stid, $this->prefetch);
}
foreach ($bindvars as $bv) {
oci_bind_by_name($this->stid, $bv[0], $bv[1], $bv[2], $bv[3]);
}
// THIS PART TAKES THE RETURN AND CREATES A BIND AND VARIABLE
oci_bind_by_name($this->stid, ':'.$return, $res, -1, SQLT_INT);
oci_execute($this->stid); // will auto commit
$this->stid = null; // free the statement resource
return($res);
}
and in my Model
function create(){
$sql ="insert into table (name, type) values (:name, :type) returning id into :id";
$id = $this->db->executeAndReturnID($sql, "table insert",
array(
array(":name", $_POST['name'], -1, SQLT_CHR),
array(":type", $_POST['type'], -1, SQLT_CHR),
),
"id" //the bind var for return into
);
return $id;
}
Okay so for some reason this query:
$db->sqlquery("INSERT INTO `password_reset` SET `user_email` = ?, `secret_code` = ?, `expires` = ?", array($email, $random_string, $next_week));
Enters "random_string" into every field and I have no idea why.
This is my query code:
public function sqlquery($sql, $objects = array())
{
global $core;
try
{
$this->STH = $this->database->prepare($sql);
foreach($objects as $k=>$p)
{
// +1 is needed as arrays start at 0 where as ? placeholders start at 1 in PDO
if(is_numeric($p))
{
$this->STH->bindParam($k+1, $p, PDO::PARAM_INT);
}
else
{
$this->STH->bindParam($k+1, $p, PDO::PARAM_STR);
}
}
return $this->STH->execute();
$this->counter++;
}
catch (PDOException $e)
{
$core->message($e->getMessage());
}
}
Any idea why it would be doing that?
PDO parameters are bound by reference. So all your parameters are being bound as references to the same $p variable, whose value when executing the query is the last element of the array.
Although you said that the value being inserted in all the fields is the second element of the array. I'm not sure why that is.
The solution is to use bindValue instead of bindParam.
As I am writing a script, I am typing $db->prepare()'s and $stmt->bindParam()'s constantly. I am looking for a way to consolidate it all in a function. This is what I have so far.
$sql = "SELECT (name, email) FROM users WHERE VALUES (:name, :email)"
$values = array(':name' => 'my_name', ':email' => 'blahblah#example.com', );
function db_query($sql, $values) {
global $db; //Database object
$stmt = $db->prepare($sql);
foreach($values as $placeholder => $value) {
$stmt->bindParam($placeholder, $value);
}
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $result;
}
Would this be sufficient for most queries? Is this a secure way to do this?
I just want the query to run and return whatever it returns (NULL, values, error, etc...).
Thanks.
Your code will not work as expected because bindParam() binds the placeholder name (first argument) to the variable reference present in the second argument.
Using your example, this would result in all parameters set to blahblah#example.com as it is the last $value in the loop.
As mentioned in the comments, simply use $stmt->execute($values). See http://php.net/manual/en/pdostatement.execute.php
If you really want to continue with your loop, use PDOStatement::bindValue() instead.
Suppose I have a function
function fetchAll(){
$args = func_get_args();
$query = array_shift($args);
$query = str_replace("%s","'%s'",$query);
foreach ($args as $key => $val) {
$args[$key] = mysql_real_escape_string($val);
}
$query = vsprintf($query, $args);
if (!$query) return FALSE;
$res = mysql_query($query);
if (!$res) {
trigger_error("db: ".mysql_error()." in ".$query);
return FALSE;
}
$a = array();
while($row = mysql_fetch_assoc($res)) $a[]=$row;
return $a;
}
and then use it like this
$a=$db->fetchAll("SELECT * FROM users WHERE status=%s LIMIT %d,%d",$status,$start,$num);
How can I rewrite it using PDO?
Every example I can find shows only how to bind parameters directly. Should I pass variable type as well as it's value? Or make this call always 4 lines - 3 binds and execute?
edit: as the Colonel indicated, apparently this (no longer?) works with LIMIT clauses.
If you're using simple queries / are not that bothered with type:
function fetchAll(){
$args = func_get_args();
$query = array_shift($args);//'SELECT * FROM users WHERE status=? LIMIT ?,?'
//you'll need a reference to your PDO instance $pdo somewhere....
$stmt = $pdo->prepare($query);
$stmt->execute($args);
return $stmt->fetchAll();
}
Every example I can find shows only
how to bind parameters directly.
Should I pass variable type as well as
it's value? Or make this call always 4
lines - 3 binds and execute?
You don't have to fire binds one line at a time; you can bind with an array like this:
# the data we want to insert
$data = array('Cathy', '9 Dark and Twisty Road', 'Cardiff');
$STH = $DBH->("INSERT INTO folks (name, addr, city) values (?, ?, ?)");
$STH->execute($data);