Conditional PDO bindParam Update - php

So I'm trying to do a conditional update but I seem to be having problems with binding the data with the statement.
function:
function updateEditor($email, $first, $last, $id){
global $DBH;
$response = false;
$upemail = "";
$upfirst = "";
$uplast = "";
$stmt = "SELECT memEmail, memFirst, memLast FROM MEMBER WHERE memID = :id";
try{
$STH = $DBH->prepare($stmt);
$STH->bindParam(':id', $id);
$STH->execute();
$STH->setFetchMode(PDO::FETCH_ASSOC);
$row = $STH->fetch();
if($row['memEmail'] != $email){ $upemail = $email;}
if($row['memFirst'] != $first){ $upfirst = $first;}
if($row['memLast'] != $last){ $uplast = $last;}
}catch(PDOException $e) {
echo $e->getMessage() . "first";
}
$stmt .= "UPDATE MEMBER SET ";
if(!empty($upemail)){
$stmt .= "memEmail = :memEmail";
if(!empty($upfirst) || !empty($uplast)){
$stmt .= ", ";
}
}
if(!empty($upfirst)){
$stmt .= "memFirst = :memFirst";
if(!empty($uplast)){
$stmt .= ", ";
}
}
if(!empty($uplast)){
$stmt .= "memLast = :memLast";
}
if(empty($upemail) && empty($upfirst) && empty($uplast)){
return false;
}else{
$stmt .= " WHERE memID = :id";
}
try{
$STH = $DBH->prepare($stmt);
if(!empty($upemail)){$STH->bindParam(':memEmail', $upemail);}else{$STH->bindParam(':memEmail', $row['memEmail']);}
if(!empty($upfirst)){$STH->bindParam(':memFirst', $upfirst);}else{$STH->bindParam(':memFirst', $row['memFirst']);}
if(!empty($uplast)){$STH->bindParam(':memLast', $uplast);}else{$STH->bindParam(':memLast', $row['memLast']);}
$STH->bindParam(':id', $id);
$STH->execute();
$STH->setFetchMode(PDO::FETCH_ASSOC);
$response = true;
}catch(PDOException $e) {
echo $e->getMessage() . "second";
$response = $e->getMessage() . "second";
}
return $response;
}
I have tried putting the variables into the statement, using ?, and the code above so far. The error I keep getting is:
SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens

Here:
$stmt .= "UPDATE MEMBER SET ";
you append the UPDATE to the previous $stmt string. You'll end up with:
$stmt = "SELECT memEmail, memFirst, memLast FROM MEMBER WHERE memID = :idUPDATE MEMBER SET "; // and the rest
reulting in one identifier more (:idUPDATE).
Remove the . to start a new query in this string.
$stmt = "UPDATE MEMBER SET ";
Note:
You are making this way too complicated. Skip the checks for empty values, just update all columns when you update a dataset, you don't gain anything by checking what has changed and what hasn't first.

Besides #Gerald Schneider answer, you are setting the param in both cases (if/else)
if(!empty($upemail)){$STH->bindParam(':memEmail', $upemail);}else{$STH->bindParam(':memEmail', $row['memEmail']);}
But are defining the parameters only in one case
if(!empty($upemail)){
$stmt .= "memEmail = :memEmail";
if(!empty($upfirst) || !empty($uplast)){
$stmt .= ", ";
}
}
if(!empty($upfirst)){
$stmt .= "memFirst = :memFirst";
if(!empty($uplast)){
$stmt .= ", ";
}
}
if(!empty($uplast)){
$stmt .= "memLast = :memLast";
}
There's no else condition

Related

Mysqli:mysqli_stmt::bind_param(): Number of variables doesn't match number of parameters in prepared statement

I am creating dynamic mysqli query with the help of #chris85. I am able to created this.
<?php
require_once 'include/db.php';
$firstname = 'Alpha';
$lastname = 'Romeo';
$query = "SELECT * FROM users";
$cond = array();
$params = array();
if (!empty($firstname)) {
$cond[] = "fname = ?";
$params[] = $firstname;
}
if (!empty($lastname)) {
$cond[] = "lname = ?";
$params[] = $lastname;
}
if (count($cond)) {
$query .= ' WHERE ' . implode(' AND ', $cond);
}
echo $query;
$stmt = $mysqli->prepare($query);
if(!empty($params)) {
foreach($params as $param) {
$stmt->bind_param("s", $param);
echo $param;
}
}
$stmt->execute();
?>
When i execute this i got this.
SELECT * FROM users WHERE fname = ? AND lname = ?
Warning: mysqli_stmt::bind_param(): Number of variables doesn't match number of parameters in prepared statement in /home/u983213557/public_html/test.php on line 32
AlphaRomeo
I am not sure why it is failing. please advise me to fix this issue.
It is failing because mysqli is not PDO and you cannot bind in a loop. Thus you have to use tricks to bind an array in mysqli. Luckily, if your PHP version is 5.6 or 7, you can use this code:
$stmt = $db->prepare($query);
$types = str_repeat('s', count($param));
$statement->bind_param($types, ...$param);
$statement->execute();
if not, then you are bound to use call_user_func()-based solution

Query doesn't insert value into DB

In my query the update statement doesn't work, the error given is:
Number of parameter doesn't match with prepared statement
this is my code:
public function update_resource($resource)
{
$mysqli = new MySQLi(HOST, USERNAME, PASSWORD, DATABASE);
$this->connection_state($mysqli);
$id = $resource['id'];
$descrizione = $resource['descrizione'];
$sigla = $resource['sigla'];
$colore = $resource['colore'];
$planning = $resource['planning'];
try
{
$query = "UPDATE risorse SET descrizione = '$descrizione'
AND sigla = '$sigla' AND colore = '$colore' AND planning = '$planning'
WHERE id = '$id' ";
$stmt = $mysqli->prepare($query);
$stmt -> bind_param("ssssi", $descrizione, $sigla, $colore, $planning, $id);
echo $query;
if($stmt->execute())
{
echo "Added!";
}
else
{
echo "Err: " . $stmt->error;
}
}catch(Exception $e){ echo $e->getMessage(); }
}
The code go into the Added condition but the query fail, what's the problem?
public function update_resource($resource)
{
$mysqli = new mysqli(HOST, USERNAME, PASSWORD, DATABASE);
if ($mysqli->connect_errno) {
echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}
$id = $resource['id'];
$descrizione = $resource['descrizione'];
$sigla = $resource['sigla'];
$colore = $resource['colore'];
$planning = $resource['planning'];
try
{
$query = "UPDATE risorse SET descrizione = '$descrizione'
, sigla = '$sigla', colore = '$colore', planning = '$planning'
WHERE id = '$id' ";
$stmt = $mysqli->prepare($query);
$stmt -> bind_param($descrizione, $sigla, $colore, $planning, $id);
echo $query;
if($stmt->execute())
{
echo "Added!";
}
else
{
echo "Err: " . $stmt->error;
}
}catch(Exception $e){ echo $e->getMessage(); }
}?
Your problem is that you don't have any placeholders in your query.
Refer to manual to see how placeholders should be set.
In general, placeholders are ? which later will be replaced with values, so your query should look like:
$query = "UPDATE risorse SET descrizione = ?
AND sigla = ? AND colore = ? AND planning = ?
WHERE id = ?";
please visit on http://php.net/manual/en/pdostatement.bindparam.php.you got your answer.see Example #1 Execute a prepared statement with named placeholders

PDO multi insert statement

I've got a working insert for a single input field but when I try to add a couple more it seems to break everything. I have a database connection working fine and including that correctly at the top of the page when I change the "isset" to have the 3 columns it breaks.
This is my set statement;
if(isset($_POST['title, question, tags']))
{
$success = insertData('questions', 'title', $_POST['title']);
$success = insertData('questions', 'question', $_POST['question']);
$success = insertData('questions', 'tags', $_POST['tags']);
if(!$success)
echo 'Sorry failed :(';
}
The function I call from a functions php file;
function insertData($tablename, $columnName, $value)
{
$sql = 'INSERT into '.$tablename.'('.$columnName.') VALUES(:Value)';
$mysqlConnection = getConnection();
$statement = $mysqlConnection->prepare($sql);
$statement->bindValue(":Value", $value, PDO::PARAM_STR);
$bReturn = false;
try
{
$statement->execute();
$bReturn = true;
}
catch(PDOExecption $e)
{
echo $e->getMessage();
}
return $bReturn;
}
Does anyone know where I'm going wrong here?
if(isset($_POST['title, question, tags']))
Is not correct syntax
instead You can do:
if(isset($_POST['title']) && isset($_POST['question']) && isset($_POST['tags']))
or even
if(isset($_POST['title'], $_POST['question'], $_POST['tags']))
It would be easier to do execute it without binding:
insertData
function insertData($tablename, $params){
//build query string
$column_string = implode(',', array_keys($params));
$value_string = implode(',', array_fill(0, count($params), '?'));
$sql_string = "INSERT INTO {$tablename} ({$columnString}) VALUES ({$value_string})";
//prepare query
$mysqlConnection = getConnection();
$statement = $mysqlConnection->prepare($sql_string);
//execute query
$success = $statement->execute(array_values($params));
//return boolean success
return $success;
}
But If you really need to bind, you can do it the following way:
function insertDataBind($tablename, $params){
//build query string
$column_string = implode(',', array_keys($params));
$value_string = implode(',:', array_keys($params));
$sql_string = "INSERT INTO {$tablename} ({$column_string}) VALUES (:{$value_string})";
//prepare query
$mysqlConnection = getConnection();
$statement = $mysqlConnection->prepare($sql);
//bind
foreach($params as $key=>$value){
$statement->bindValue($key, $value);
}
//execute query
$success = $statement->execute();
//return boolean success
return $success;
}
usage:
if(isset($_POST['title'], $_POST['question'], $_POST['tags'])){
$params = array('title' => $_POST['title'],
'question'=>$_POST['question'],
'tags'=>$_POST['tags']
);
$success = insertData('questions', $params);
if(!$success)
echo 'Sorry failed :(';
}

How to put PDO bindParam in if statement?

How to put PDO bindParam in if statement? I tried to do a different variations, but none of them worked.
function get_all_pages($subject_id, $public = true)
{
$db = new PDO('mysql:host=localhost;dbname=name;charset=utf8', 'root', 'whatewer');
$query = "SELECT * ";
$query.= "FROM pages ";
$query.= "WHERE subject_id =:id ";
if ($public)
{
$query.= " AND visible =:visible ";
}
$query.= "ORDER BY position ASC";
$query.= "ORDER BY position ASC";
$stmt = $db->prepare($query);
if ($public)
{
$stmt->bindParam(':id', $subject_id, PDO::PARAM_INT);
$stmt->bindValue(':visile', 2, PDO::PARAM_INT);
}
else
{
$stmt->bindParam(':id', $subject_id, PDO::PARAM_INT);
}
$stmt->execute();
$affected_rows = $stmt->rowCount();
if ($affected_rows == 1)
{
$subject = $stmt->fetch(PDO::FETCH_ASSOC);
return $subject;
}
}
else
{
return null;
}
}
Ok there was misunderstanding I got my cod "Wright" it was stackoverflow that messed my code up. i was struggling to put code in code area. In reality it looks like this.
http://imagizer.imageshack.us/v2/800x600q90/593/zvf8.png
$affected_rows = $stmt->rowCount(); might give you unexpected results as according to the manual:
For most databases, PDOStatement::rowCount() does not return the
number of rows affected by a SELECT statement.
You should fetch a row directly and see what the result is:
$stmt->execute();
if ($subject = $stmt->fetch(PDO::FETCH_ASSOC))
{
return $subject;
}
else
{
return null;
}
And I would recommend opening your database connection as I mentioned in my comment:
$db = new PDO('mysql:host=localhost;dbname=name;charset=utf8', 'root',
'whatewer', array(PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING));
That will cause PDO to throw exceptions and that will give you a clear error message whenever something goes wrong on any of the db calls.

MySQL update, skip blank fields with PDO

I would like to update a MySQL row via the form below. The form works great as is but, if I leave a field blank, it changes the field in MySQL to blank as well. I would like to update the sql but skip over any fields that are blank.
I have read a few ways of doing this but they didn't seem logical. I.e. using if statements in the sql string itself. (Having MySQL do the work that should be done in PHP).
if($_SERVER['REQUEST_METHOD'] != 'POST')
{
echo '<form method="post" action="">
ID: <input type="text" name="a" /><br>
Program: <input type="text" name="b" /><br>
Description: <textarea row="6" cols="50" name="c"></textarea><br>
Cost: <input type="text" name="d"><br>
<input type="submit" value="Add Link" />
</form>';
}
try {
$dbh = new PDO($dsn, $user, $pass);
$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$stmt = $dbh->prepare('UPDATE links SET Program = :program , Descr = :descr, Cost = :cost WHERE Id= :id');
$stmt->bindParam(":id", $_POST["a"]);
$stmt->bindParam(":program", $_POST["b"]);
$stmt->bindParam(":descr", $_POST["c"]);
$stmt->bindParam(":cost", $_POST["d"]);
$stmt->execute();
if (!$stmt) {
echo "\nPDO::errorInfo():\n";
print_r($dbh->errorInfo());}
$dbh = null;
}
}catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
Something like this should work
.
.
.
$q = array();
if(trim($_POST["b"]) !== ""){
$q[] = "Program = :program";
}
if(trim($_POST["c"]) !== ""){
$q[] = "Descr = :descr";
}
if(trim($_POST["d"]) !== ""){
$q[] = "Cost = :cost";
}
if(sizeof($q) > 0){//check if we have any updates otherwise don't execute
$query = "UPDATE links SET " . implode(", ", $q) . " WHERE Id= :id";
$stmt = $dbh->prepare($query);
$stmt->bindParam(":id", $_POST["a"]);
if(trim($_POST["b"]) !== ""){
$stmt->bindParam(":program", $_POST["b"]);
}
if(trim($_POST["c"]) !== ""){
$stmt->bindParam(":descr", $_POST["c"]);
}
if(trim($_POST["d"]) !== ""){
$stmt->bindParam(":cost", $_POST["d"]);
}
$stmt->execute();
}
.
.
.
Change the statement:
$stmt = $dbh->prepare('UPDATE links SET Program = :program , Descr = :descr, Cost = :cost WHERE Id= :id');
As follows:
$stmt = $dbh->prepare('UPDATE links SET Program = IF(trim(:program)="", Program, :program) , Descr = IF(trim(:descr)="", Descr, :descr), Cost = IF(trim(:cost)="", Cost, :cost) WHERE Id= :id');
Check post field for empty :
It will skip update query if any field data is empty.
If( $_POST["a"] && $_POST["b"] && $_POST["c"] && $_POST["d"]){
try {
$dbh = new PDO($dsn, $user, $pass);
$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$stmt = $dbh->prepare('UPDATE links SET Program = :program , Descr = :descr, Cost = :cost WHERE Id= :id');
$stmt->bindParam(":id", $_POST["a"]);
$stmt->bindParam(":program", $_POST["b"]);
$stmt->bindParam(":descr", $_POST["c"]);
$stmt->bindParam(":cost", $_POST["d"]);
$stmt->execute();
if (!$stmt) {
echo "\nPDO::errorInfo():\n";
print_r($dbh->errorInfo());}
$dbh = null;
}
}catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
}
Option2 Update all fields except empty:
try {
$sql ="UPDATE links SET ";
if($_POST["a"])
$sql .=" Program = :program ,";
if($_POST["b"])
$sql .=" Descr = :descr ,";
if($_POST["c"])
$sql .=" Cost = :cost ,";
$sql = rtrim($sql,',');
$dbh = new PDO($dsn, $user, $pass);
$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$stmt = $dbh->prepare($sql);
if($_POST["a"])
$stmt->bindParam(":id", $_POST["a"]);
if($_POST["b"])
$stmt->bindParam(":program", $_POST["b"]);
if($_POST["c"])
$stmt->bindParam(":descr", $_POST["c"]);
$stmt->execute();
if (!$stmt) {
echo "\nPDO::errorInfo():\n";
print_r($dbh->errorInfo());}
$dbh = null;
}
catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
It is easier to use unnamed parameters for dynamic queries in PDO and passing them as an array in execute(). The statement will not be executed unless at least 1 parameter is passed along with the id. I have left in the echo of the derived statement and the dump of the array.
Example statement
UPDATE `links` SET `Program` = ? , `Cost` = ? WHERE `Id` = ?
Example array
Array ( [0] => 2 [1] => 3 [2] => 2 )
if(isset($_GET['a'])){
$id = $_GET['a'];
$program = isset($_GET['b']) ? $_GET['b'] : NULL;
$descr = isset($_GET['c']) ? $_GET['c'] : NULL;
$cost= isset($_GET['d']) ? $_GET['d'] : NULL;
$params =array();
$sql = "UPDATE `links` SET "; //SQL Stub
if (isset($program)) {
$sql .= " `Program` = ? ,";
array_push($params,$program);
}
if (isset($descr)) {
$sql .= " `Descr` = ? ,";
array_push($params,$descr);
}
if (isset($cost)) {
$sql .= " `Cost` = ? ,";
array_push($params,$cost);
}
$sql = substr($sql, 0, -1);//Remove trailing comma
if(count($params)> 0){//Only execute if 1 or more parameters passed.
$sql .= " WHERE `Id` = ? ";
array_push($params,$id);
echo $sql;//Test
print_r($params);//Test
$stmt = $dbh->prepare($sql);
$stmt->execute($params);
}
}

Categories