dynamic PDO mysql update - php

I have a form with many optional fields. I am using PHP and PDO to collect the data from the forms and store it in a DB.
Since some optional fields may be empty, I only want to store inputs that actually have value. I can easily identify the inputs that have value, but without using a whole lot of IF statements, I can't seem to find a way to ONLY insert a value into the DB if it exists.
My current PDO looks something like this:
$data = array($var1, $var2, $var3, $var4, $var5, $var6);
$STH = $DBH->("INSERT INTO users (first, last, addr, city, email, phone) values (?, ?, ?, ?, ?, ?)";
$STH->execute($data);
Is there a way to only update a column if a value in the array exists?
Example: if $var3 and $var4 are empty, nothing is stored in the DB for "addr" and "city"?

For any other noobs out there, turns out inserting null values into a database is acceptable as long as you have your mysql rows up to allow null. You may also want to give them a default value of null.
See this post:
MySQL, better to insert NULL or empty string?
Thanks to everyone for the help.

Ideally, you'd set up the table to not allow null values for those fields. Otherwise, on the PHP side you could just check if the values have been set and are not null:
if (isset($var1, $var2, $var3, $var4, $var5, $var6)) {
$data = array($var1, $var2, $var3, $var4, $var5, $var6);
$STH = $DBH->("INSERT INTO users (first, last, addr, city, email, phone) values (?, ?, ?, ?, ?, ?)";
$STH->execute($data);
}
Unless you want to still insert? In which case just initialize the values to an empty string or whatever:
$data = array($var1?:"", $var2?:"", $var3?:"", $var4?:"", $var5?:"", $var6?:"");

Related

How to use PHP prepare with zillions of fields of different types

I am inserting data that has VARCHAR, TIMESTAMP and DECIMAL kinds using prepare.
The data is already in the format needed by mySQL.
My problem is this. Suppose I had only 2 items to insert. I would do like this:
$stmt = $mysqli->prepare("INSERT INTO myTable (name, age) VALUES (?, ?)");
$stmt->bind_param("si", $_POST['name'], $_POST['age']);
My problem is the bind part. How do I do the bind when I have to insert 40 columns at once?
I can deal with the prepare part by doing this:
$sql = "INSERT INTO customers ($columns) VALUES ($values)";
$stmt = $mysqli->prepare($sql);
But the next line will result in a ridiculous long line, impossible to understand and very easy to go wrong.
$stmt->bind_param("ssssiidisisssiidiisssidiisidi", ....);
I don't see how I could build that in a loop for example.
How do I do that?
You can pass an array to the mysqli_stmt::bind_param() function as variable arguments with the ... syntax, introduced in PHP 5.6.
$params = ['name', 42];
$stmt = $mysqli->prepare("INSERT INTO myTable (name, age) VALUES (?, ?)");
$stmt->bind_param(str_repeat('s', count($params)), ...$params);
$stmt->execute();
You don't really need to set the data type individually for each column. You can treat them all as 's'.
I know you're asking about mysqli, but I'll just point out that this is easier with PDO:
$params = ['name', 42];
$stmt = $pdo->prepare("INSERT INTO myTable (name, age) VALUES (?, ?)");
$stmt->execute($params);

Shorter way of binding too many variables in prepared statement

I am using the prepared statement for CRUD in PHP. My code snippet :
$SQL="INSERT INTO Dress(DressID, Description, Size, Price, EntryDate, CategoryID, ColorID)
VALUES (?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE Description=?, Size=?, Price=?, EntryDate=?, CategoryID=?, ColorID=?";
$stmt=$connection->prepare($SQL);
$stmt->bind_param("ssssss", $ColorID, $Color, $Color);
Then, I have to repeat the variables binding in bind_param function, like bind_param("sssssssss", $var1, $var2, $var1, $var2, $var3..).
Is there any way to shorten this binding?
You can pass the parameters to the ->execute() method, like this:
$stmt->execute([123, 'red', 'green', ... ]);
If you keep the parameters in an array, instead of assigning them to variables, then binding them to the prepared statement can become rather trivial.

Insert into table with prepared statement

I'm trying to insert data from a form into a database using PHP and Mysqli but I can't get it working! My database has 4 fields: DATE, TITLE, CONTENT, ID. The ID field is auto-increment.
I've checked the connection and that's working fine. I've also echoed the form field values and the $blogDate variable I created, they're all fine too.
Here's my prepared statement:
if ($newBlog = $mysqli->prepare('INSERT INTO Blog VALUES ($blogDate, $_POST["bTitle"], $_POST["bContent"])')) {
$newBlog->execute();
$newBlog->close();
}
It's just not inserting the values into my table.
You are generating SQL containing strings that are not quoted or escaped.
Don't insert the data directly into the SQL string, use placeholders (?) and then bind the parameters before executing.
$query = "INSERT INTO Blog VALUES (?, ?, ?)";
$stmt = $mysqli->prepare($query);
$stmt->bind_param("sss", $blogDate, $_POST["bTitle"], $_POST["bContent"]);
$stmt->execute();
Since you are aware about prepared statement:
$newBlog = $mysqli->prepare('INSERT INTO Blog (`dateCol`, `titleCol`, `contentCol`) VALUES (?, ?, ?)');
$newBlog->bind_param( 'sss', $blogDate, $_POST["bTitle"], $_POST["bContent"] );
$newBlog->execute();
$newBlog->close();
since you are using auto increment field you need to specify column name and then values
try this code
$query = "INSERT INTO Blog (colname_1,colname_2,colname_3) VALUES (?, ?, ?)";
$stmt = $mysqli->prepare($query);
$stmt->bind_param("sss", $blogDate, $_POST["bTitle"], $_POST["bContent"]);
$stmt->execute();

If I use $_POST value directly in bindParam (mysqli) will there be a security issue?

I have been reading about using $_POST values being used directly in isert statements and understand that this is an invitation for trouble. What is not clear in any of the posts I read was -
Say my form is sending 7 items to my mysqli insertion script and I use the posted values like this:
$stmt = $mysqli->prepare("INSERT INTO `advertisements` (`from`, `r_u_res`, `email`, `blockname`, `floorno`, `doorno`, `content`) VALUES (?, ?, ?, ?, ?,?,?)");
$stmt->bind_param('sssssss', $_POST['from'], $_POST['rures'], $_POST['email'], $_POST['blockname'], $_POST['floorno'], $_POST['doorno'], $_POST['content']);
$stmt->execute();
$stmt->close();
Would that be the correct way to do it? Or should I first store the posted values in a new variable and use that variable while binding? - like this :
$postedfrom = $_POST['from'];
$postedrures = $_POST['rures'];
$postedemail = $_POST['email'];
$postedblockname = $_POST['blockname'];
$postedfloorno = $_POST['floorno'];
$posteddoorno = $_POST['doorno'];
$postedcontent = $_POST['content'];
$stmt = $mysqli->prepare("INSERT INTO `advertisements` (`from`, `r_u_res`, `email`, `blockname`, `floorno`, `doorno`, `content`) VALUES (?, ?, ?, ?, ?,?,?)");
$stmt->bind_param('sssssss', $postedfrom, $postedrures, $postedemail, $postedblockname, $postedfloorno, $posteddoorno, $postedcontent);
$stmt->execute();
$stmt->close();
I saw a post OO mysqli prepared statements help please where the answer does seem to be like the code above but I want to know whether doing it like the first code poses security issues...
both forms are equivalent from a security perspective as php first resolves the values to be passed in the method call to $stmt->bind_param, thus that function sees the exact same values in both cases.
ps: both snippets look ok to me.

Prepared statement mysqli

I'm getting obsessed. I'm working for the first time with prepared statement and I am sure I have read somewhere that you could prepare a statement like:
$stmt = $db->prepare("INSERT INTO {$table} (:var1, :var2) VALUES (:val1, :val2)");
$stmt->bind_param(':var1', $var1);
$stmt->bind_param(':var2', $var2);
$stmt->bind_param(':val1', $val1);
$stmt->bind_param(':val2', $val2);
$stmt->execute();
Or something like that. I remember that I have read that you could call the vars with a specific name with ':' as prefix. But I really can't find an example of that. I read the php manual and I couldn't find any sample of this thing.
Is it right or have I dreamed it?
Faq
If you are wondering why I can't use simply the '?' method:
$stmt = $db->prepare("INSERT INTO {$table} (?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?)");
this gets hard to write.
You can't do :var1,:var2,:varX in both the column names list and the VALUES list for one thing. Secondly, PDO accepts named parameter binding.
See PHP Data Objects and examples in PDO::prepare.

Categories