PHP: form select box doesn't write changed selection to DB - php

Okay, so I have this form that is set to preload a DB record for editing if you add a ?edit=1 to the url, it will load record #1 for editing into the form. I have a box that is like this-
<select class="field select addr">
<option value="no"<?php if($row['has_amenities'] == "no") {echo ' selected=\"selected\"'; } ?>>No</option>
<option value="yes"<?php if($row['has_amenities'] == "yes") {echo 'selected=\"selected\"'; } ?>>Yes</option>
</select>
Now, let's say that $row['has_amenities'] is "yes" so when the form loads, the select box is showing "Yes".
BUT, if I change the select box to "No" and click save, it doesn't write "no" to the DB, but it does wipe out that record's "yes" with nothing.
What am I doing wrong?
Here's the update code--
$sql = "UPDATE venues SET microsite_title = '$_POST[microsite_title]',
microsite_city_title = '$_POST[microsite_city_title]', logo = '$_POST[logo]', photo1 =
'$_POST[photo1]', photo2 = '$_POST[photo2]', photo3 = '$_POST[photo3]', photo4 =
'$_POST[photo4]', photo5 = '$_POST[photo5]', photo6 = '$_POST[photo6]', photo7 =
'$_POST[photo7]', photo8 = '$_POST[photo8]', website_primary = '$_POST[website_primary]',
website_secondary = '$_POST[website_secondary]', paragraph_1_title =
'$_POST[paragraph_1_title]', paragraph_1 = '$_POST[paragraph_1]', paragraph_2_title =
'$_POST[paragraph_2_title]', paragraph_2 = '$_POST[paragraph_2]', paragraph_3_title =
'$_POST[paragraph_3_title]', paragraph_3 = '$_POST[paragraph_3]', paragraph_4_title =
'$_POST[paragraph_4_title]', paragraph_4 = '$_POST[paragraph_4]', paragraph_5_title =
'$_POST[paragraph_5_title]', paragraph_5 = '$_POST[paragraph_5]', paragraph_6_title =
'$_POST[paragraph_6_title]', paragraph_6 = '$_POST[paragraph_6]', top10_1 =
'$_POST[top10_1]', top10_2 = '$_POST[top10_2]', top10_3 = '$_POST[top10_3]', top10_4 =
'$_POST[top10_4]', top10_5 = '$_POST[top10_5]', top10_6 = '$_POST[top10_6]', top10_7 =
'$_POST[top10_7]', top10_8 = '$_POST[top10_8]', top10_9 = '$_POST[top10_9]', top10_10 =
'$_POST[top10_10]', top10_locale = '$_POST[top10_locale]', contact_title =
'$_POST[contact_title]', contact_street_addr = '$_POST[contact_street_addr]',
contact_street_addr2 = '$_POST[contact_street_addr2]', contact_city =
'$_POST[contact_city]', contact_state = '$_POST[contact_state]', contact_zip =
'$_POST[contact_zip]', contact_phone = '$_POST[contact_phone]', contact_tollfree =
'$_POST[contact_tollfree]', latitude = '$_POST[latitude]', longitude = '$_POST[longitude]',
testimonial = '$_POST[testimonial]', sidebar_title = '$_POST[sidebar_title]',
sidebar_content = '$_POST[sidebar_content]', has_amenities = '$_POST[has_amenities]'
WHERE id = '$_POST[query]'";
Also, I know it's not a good idea to write $_POST values without cleaning them first, but this is an internal form behind a firewall, etc. I'll clean it up later after it's working :o)
Thanks!

It looks like the <select> element has no name or id--is that the case in your code? If so, I believe $_POST[has_amenities] won't be set--there would be no has_amenities value in $_POST. You'd get an empty string instead.

Wrap all of the instances of $_POST[] in {} (curly braces) so it looks like this
'{$_POST['key']}'
The curly braces are need to force PHP to evaluate $_POST as a variable when it's inside a double-quoted string.
Also, quote your $_POST array keys like this
$_POST['key']
You want to get in the habit of this even though $_POST[key] will usually work. PHP is treating key as an constant which, if it's undefined, is automatically turned into a the string "key" so you get the behavior you're expecting.
However, if key already exists as a constant (via the define()) function, you'll get the value of the key constant which is not what you want.
Take a look at the Array do's and don'ts section.

Try wrapping your array variables with curly braces like so:
'$_POST[paragraph_3]' = '{$_POST[paragraph_3]}'

You'll need to specify a name for this select tag. I also see you're escaping your double-quotes with backslashes, which is unnecessary (it will literally use \" so the output would look like: selected=\"selected\" which is bad html).
Try using this:
<select name="has_amenities" class="field select addr">
<option value="no"<?php if($row['has_amenities'] == "no") {echo ' selected="selected"'; } ?>>No</option>
<option value="yes"<?php if($row['has_amenities'] == "yes") {echo 'selected="selected"'; } ?>>Yes</option>
</select>
Your SQL statement will work the way it is, but not that if a single quote is entered by the user, it will break the statement...possibly causing a huge security hole. Check out "SQL injection" on the google.

Related

Removing empty spaces and BR from string in echo

I got the below code but at the moment it generates a string of results but with about 40+ empty spaces.
$user_ = JFactory::getUser();
$db = JFactory::getDBO();
$levels = JAccess::getAuthorisedViewLevels($user->id);
foreach($levels as $key => $level)
{
$query = 'SELECT title FROM #__pf_projects';
$query .= ' WHERE access = ' . $level . " AND TRIM(title) != ''";
$db->setQuery($query);
$projectlist = $db->loadResult($query).'<br>';
echo $projectlist;
}
At first I thought that array_filter() would be good here but as PatrickQ points out it is a string so the array filter won't work.
Then I adapted the code according to the answer from Don't Panic. This adapted code is what you can see above.
It returns now a list like this.
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
http://www.domain1.com
<br>
<br>
<br>
<br>
http://www.domain5.com
http://www.domain23.com
http://www.domain65.com
http://www.domain213.com
<br>
<br>
<br>
<br>
<br>
<br>
So how to adapt the code to just get a list like this:
http://www.domain1.com
http://www.domain5.com
http://www.domain23.com
http://www.domain65.com
http://www.domain213.com
When you change the <br> into a , then the list becomes ,,,,,,,,,,,http,,,,,,httphttphttphttp,,,,,,, <= I wrote it down a bit shorter.
First thing, array_filter, if no callback was passed, will remove only falsy elements. String with empty spaces is evaluated to true and therefore will not be remove from array. You can do something like:
$filteredArray = array_filter($projectList, function($val) {
return trim($val);
});
print_r($filteredArray);
Also, you can't echo an array. You can use print_r or var_dump.
If array_filter isn't filtering out empty values, then they probably aren't really empty. Assuming there is some sort of whitespace there rather than nulls or empty strings, you can probably modify your query to trim the title and only return results where there's still something there.
SELECT title FROM #__pf_projects
WHERE access = ? AND title IS NOT NULL AND TRIM (title) != ''
Or, in terms of your original PHP code:
$query = 'SELECT title FROM #__pf_projects';
$query .= ' WHERE access = ' . $level . " AND TITLE IS NOT NULL AND TRIM(title) != ''";
It is best to avoid concatenating variables into your SQL like this, though. If the framework you're using has some way to utilize prepared statements, you should go that route instead.
If this still doesn't work, I don't really know what else to try with the query, but you should be able to just check for an empty result in PHP and only echo if there's something to show.
$projectlist = $db->loadResult($query);
if (trim($projectlist)) echo $projectlist.'<br>';
Thanks to everyone's answers I finally figured out a way to get the results. My way is not necessarily the right way for everyone. And someone with more knowledge then me in this area would probably do it different.
Essentially my answer is outputting the entire string with each result inside a div. This will create a lot of empty divs but those are not generated by HTML. They do however show up in the Inspector.
The final code that I use in my script.
$user_ = JFactory::getUser();
$db = JFactory::getDBO();
$levels = JAccess::getAuthorisedViewLevels($user->id);
foreach($levels as $key => $level)
{
$query = 'SELECT title FROM #__pf_projects';
$query .= ' WHERE access = ' . $level;
$db->setQuery($query);
$projectlist = '<div class="project">'.$db->loadResult($query).'</div>';
echo $projectlist;
}
This is now giving me a list like this:
http://www.domain1.com
http://www.domain5.com
http://www.domain23.com
http://www.domain65.com
http://www.domain213.com

How to block inserting empty strings in MySQL

I have this update statement (PHP code):
$sql1="UPDATE `utilizatori` " .
"SET utilizator='$utilizator', parola='$parola1', nume='$nume', " .
"`prenume='$prenume', varsta='$varsta', localitate='$localitate'` ";
WHERE parola='".$_SESSION['parola']."'";
This will update some MySQL table fields via an html form. The user wants to change just his name for instance. He completes just name field, then he presses submit. The data is sent into the table with the UPDATE statement above.
The problem is that it also updates the table with blank values that user didn't complete. I don't want the blank values to be added.
How can I block the blank values to be sent into the table?
If you really wanted to do this in the update, you can change the set statement to something like:
set utilizator = (case when '$utilizator' <> '' then '$utilizator' else utilizator end),
. . .
This will use the previous value if the new one is blank.
You can also do this at the application level by just updating the fields that have changed.
And, you should use parameterized queries rather than directly substituting values into a string. That is another issue, though.
You can do two things to solve this issue. One is to preload the data in the form. So when the user change his name, the other fields are already loaded with the original information.
The second option is to create an update query based on the fields have a value.
Example of option 1:
<?php
//
//GET THE DATA FROM A SELECT QUERY HERE
//FOR EXAMPLE: $sql = "SELECT * FROM `utilizatori` WHERE parola='".$_SESSION['parola']."'";
//Put the data of the sql row in a variable e.g. $sqlRow.
?>
<!--Use variable in your form!-->
<form>
...
...
<input name="nume" value="<?=$sqlRow['nume']?>"/>
<input name="utilizator" value="<?=$sqlRow['utilizator']?>"/>
...
...
</form>
Example of option 2:
<?php
//Catch post data
if($_POST)
{
$updateString = "";
foreach($_POST as $inputField => $inputValue)
{
if($inputValue != "")
{
$updateString .= $inputField." = '".$utilizator."',";
}
}
//Strip last ,
$updateString = substr($updateString,0,-1);
if($updateString != "")
{
//Your query would be
$sql1 = "UPDATE `utilizatori` SET ".$updateString." WHERE parola='".$_SESSION['parola']."'";
}
}
?>
$updateClauseArr = Array();
foreach($_REQUEST as $key => $val){
if(is_numeric($val)){
$updateClauseArr[] = '$key = '.(int) $val;
}else{
$updateClauseArr[] = "$key = '".htmlentities($val,ENT_QUOTES,'UTF-8')."'";
}
}
if(sizeof($updateClauseArr) > 0){
$updateSet = implode(',' ,$updateClauseArr);
$sql1="UPDATE `utilizatori` SET ".$updateSet." WHERE parola='".$_SESSION['parola']."'";
}
See what field values have been submitted by the user. then iterate in a loop for the fields that have value to make variable to be concatenated to the update query.

How to Insert DropDown Selection into MySQL database?

I am trying to post the value chosen for a dropdown menu into my database table. But for some reason its not inputting the value into the database. I am trying to post cat_id into my database. So i use the code below to geenrate my dropdown list from values i alrady have in the database. Then below i have the function that inserts the info into the database. But for some reason its not working. I am suppose to put what is in select name="" right?
<select name="cat[<?=$row['pk_id']?>]">
<?php $cat = dbConnect("SELECT * FROM category");
if(empty($row['cat_id'])){
?>
<option value="">Select Category</option>
<?php
}
?>
<?php while($cat_r = mysql_fetch_array($cat)){
if($row['cat_id'] == $cat_r['cat_id']){
?>
<option value="<?=$cat_r[cat_id]?>" selected="selected"><?=stripslashes($cat_r[cat_name])?></option>
<?php
continue;
}
?>
<option value="<?=$cat_r[cat_id]?>"><?=stripslashes($cat_r[cat_name])?></option>
<?php } ?>
</select>
Here is my insert to MySQL
dbConnect("INSERT INTO post_info(add_to_random, show_home, source, display_vote_page, cat_id) values(1,1,1,0,cat[.$row['pk_id'].])");
Did i put something wrong here for the value for cat_id? I put cat[.$row['pk_id'].]) which is the select name="" for that dropdown list.
Code ported from comment:
if($_POST and $_POST['action'] == 'submit'){
foreach($_POST as $k=>$v){
$$k = $v;
}
foreach($cat as $k=>$v){
if($v =='') continue;
dbConnect("UPDATE twit_info set cat_id=" . $v . " where pk_id =". $k );
}
if(count($pkid)>0){
$pid = implode(',',$pkid);
dbConnect("UPDATE twit_info set add_to_vote = 1, display_vote_page = 1 where pk_id in(". $pid .")");
}
}
So in your foreach loop, you are extracting all post keys into global variables via the variable variable $$k (I'll get to this in a second). In your dbConnect() call, the quoting is incorrect. You should concatenate in $cat.
dbConnect("
INSERT INTO post_info
(add_to_random, show_home, source, display_vote_page, cat_id)
values(1,1,1,0, '" . mysql_real_escape_string($cat[$row['pk_id']]) . "')" );
I have added a call to mysql_real_escape_string(). This is necessary at a minimum, to protect all your queries from SQL injection. Your other UPDATE statements are also vulnerable at this point and you MUST perform some escaping on them as well.
Regarding the extraction of $_POST into global variables - I highly recommend against this. You are in effect imitating the behavior of register_globals which is considered very dangerous. The danger comes in that it is possible for anyone to post any key to your form, in addition to the ones you actually expect to receive, potentially initializing another variable in your script to a value sent via $_POST when your script doesn't expect it.
Although I really just recommend operating on $_POST directly, rather than extracting to global variables, if you must extract them to globals, I advise you to use a whitelist of acceptable $_POST keys:
// Make an array of allowed keys
$good_keys = ('action', 'cat', 'otherformkey');
foreach($cat as $k=>$v){
// Only extract if it is one of the allowed keys
if($v =='' || !in_array($k, $good_keys) continue;
// Cast to an integer
$v = intval($v);
$k = intval($k);
// Non-integer strings will cast to zero, so don't do the db action.
if ($v > 0 && $k > 0) {
dbConnect("UPDATE twit_info set cat_id=" . $v . " where pk_id =". $k );
}
// For string values which are quoted in the SQL (unlike the int values above)
// escape them with mysql_real_escape_string()
// $v = mysql_real_escape_string($v)
}

Creating an SQL query when the values to be used in the query are unknown

I have some search functionality that works with 3 drop down boxes. Based on the criteria chosen, a profile is returned. The 3 drop downs are:
County
Constituency
Gender
Now I am trying to build a query but have just realised that actually a person does not have to choose an option from each drop down and nor do I want them to.
So for instance I do not want to disable the search button until an option is selected from each drop down.
Having chosen a value from any drop down, and possibly having no value selected from any drop down at all, and just clicking the search button, I am trying to understand how I can cope with the unknown combinations.
My first thought was that I could use something like a truth table but I imagine this is simply overkill and in fact this is a very common piece of functionality.
Then I thought maybe I could have something like:
$county = "$_GET['county'];";
$constituency = "$_GET['constituency'];";
$gender = "$_GET['gender'];";
Then I could check to see if they are empty and somehow use this value, e.g.
if($county !== '') {
???SOMEHOW MAKE USE OF THIS IN AN SQL QUERY???
PERHAPS PASS IT TO ANOTHER PARAMETER
$sqlparams = "county = '$county'";
}
SELECT * FROM profile
WHERE {$sqlparams};
I think I'm on the right tracks but could use some guidance.
All help is greatly appreciated.
This should do want you want, I think.
<?php
$tooLookFor = array("county", "constituency", "gender");
foreach($tooLookFor as $key){
if(isset($_GET[$key]) && strlen($_GET[$key])>0){
$queryParams[] = $key.'="'.$_GET[$key].'"';
}
}
$query = "SELECT * FROM profile WHERE ".implode(' AND ', $queryParams);
?>
You could do something like:
$county = $_GET['county'];
$constituency = $_GET['constituency'];
$gender = $_GET['gender'];
$sqlparams = array();
if($county !== '') {
$sqlparams[] = "county = '$county'";
}
if($constituency !== '') {
$sqlparams[] = "constituency = '$constituency'";
}
if($gender !== '') {
$sqlparams[] = "gender = '$gender'";
}
$query = "SELECT * FROM profile";
if (count($sqlparams) > 0) {
$query .= " WHERE " . implode(" AND ", $sqlparams);
}
You can do that with something like this:
$where = array();
//repeat as needed
$where[$column] = $value;
$where2 = array();
foreach($where as $key => $value){
$where2[] = "$key = '$value'";
}
$where_string = implode(' AND ', $where2);
$where_string will have the string to insert after WHERE.
Yes, you are on the right track, you're just not at the right switch yet. ;)
You can't build the query until you know what you have to work with. So first, in your validation, determine (as you are doing) with the key words actually are and what fields they represent. Presumably these map to fields in tables, maybe 3 tables? Point is, your query will need to be dynamically built.

how to loop through a set of GET values in php

I'm making a simple online store like program. What can you suggest that I would do so that I can loop through the inputs I've made in my program.
I'm still using get so that I could see how the data looks like, I'll change it to post later.
This is what the url looks like, when I commit the buying of all the products added in the cart:
http://localhost/pos/php/checkout.php?ids=2;&qoh=12;&qbuys=&ids=6;&qoh=2304;&qbuys=304&ids=4;&qoh=699;&qbuys=99
This is the code that I'm using to commit only one product, it doesn't work when I had something like in the above url:
<?php
$id=$_GET['ids'];
$qtyhnd=$_GET['qoh'];
$qtytbuy=$_GET['qbuys'];
$left=$qtyhnd-$qtytbuy;
if($qtyhnd>=$qtytbuy){
$update=query_database("UPDATE prod_table SET QTYHAND='$left' WHERE PID='$id'", "onstor", $link);
}
?>
Please comment if you need more details,thanks
Either convert the parameters to array parameters (e.g. qoh[]) and then iterate in parallel, or parse the query string manually.
You have semicolons after some values maybe you should pass just the integer this are qoh and qbuys.
Apart of that you should use mysql_real_escape_string() and (int) before integer values to prevent SQL injection e.g.:
$int = (int)$_GET['price'];
$string = $_GET['val'];
mysql_real_escape_string($string);
Also if you want to pass multiple values you have to use array for them:
HTML
<input type="hidden" name="ids[]" value="1">
<input type="hidden" name="ids[]" value="2">
<input type="hidden" name="ids[]" value="3">
PHP
$ids = $_GET['ids'];
foreach($ids as $id) {
$sql = 'UPDATE table SET field=? WHERE id='.(int)$id;
....
}
You can use the $_SERVER['QUERY_STRING'] with foreach loop like this:
foreach($_SERVER['QUERY_STRING'] as $key => $value){
echo "$key - $value <br />";
}
This way you can get the values of GET and use in your database query in similar fashion using foreach loop.
I assume that PID in prod_table is of integer type. Doesn't $id variable contain "2;" instead of 2? Anyway, what kind of error do you get?
Have your url like
http://localhost/pos/php/checkout.php?ids[]=2&qoh[]=12&qbuys[]=&ids[]=6&qoh[]=2304&qbuys[]=304&ids[]=4&qoh[]=699&qbuys[]=99... using a HTML structure like infinity pointed out.
Then:
foreach ($_GET['ids'] as $k => $v) {
$id = (int)$v;
$qtyhnd = (int)$_GET['qoh'][$k];
$qtytbuy = (int)$_GET['qbuys'][$k];
$left = $qtyhnd - $qtytbuy;
if ($qtyhnd >= $qtytbuy) {
$update = query_database(
"UPDATE prod_table SET QTYHAND='$left' WHERE PID='$id'",
"onstor",
$link);
}
}
And if the database type of QTYHAND and PID are int, exclude single quotes (') from your SQL queries.

Categories