PHP Form Posting Values To Database - php

Basically, i have a working form where the user inputs details about their laptop to sell to my shop.
I give them a quote once they have submitted the Specs of the laptop.
At the moment i have got option boxes and checkboxes which each have a value-- for example these. ---
<label for="state">State</label><br>
<select name="state">
<option value="10">Excellent</option>
<option value="5">Good</option>
<option value="0">Poor</option>
</select><br>
The Values of the options they have selected get added up at the end and that gives them the quote - in the above example - "10" means £10 extra for a excellent condition laptop etc.
I use $_POST[state] to get the value of it to add onto the other options for the quote.
But my problem lies when i POST them to a database (so we can check when they come in).
When they get added to the database, obviously it just comes out as the values not the actually name of it like "excellent" or "good". just says "10" or "5".
Is there anyway to put the name of the option into the database instead of the value?

sure... just make sure that's what you want to do. It's usually not considered a good database practice to create denormalized tables like that, but you could do it. When you collect your post data, simply create another variable and assign a value to it based off the state value like so:
$stateText = '';
switch ($state){
case 10:
$stateText = 'Excellent';
break;
case 5:
$stateText = 'Good';
break;
case 0:
$stateText = 'Poor';
break;
default:
// bad value
$stateText = '';
}
...then store this to the database in a new column.
This is just one of many ways to do this.

You can only do it if you have a lookup, be it an array or in another table that stores the keys and values.
You should be carefuly not to store the post data directly into your database without sanitizing it, otherwise you might become subject to sql injection.

Is there anyway to put the name of the option into the database instead of the value?
There is, but it involves doing it explicitly (converting "10" into "Excellent" before inserting the value) rather than just basically tossing $_POST into the database as-is. You can make this very simple if you are building the <option>s with an array in the first place by reading the the array again and swapping the values with the keys.
$values = array(
10 => 'Excellent',
5 => 'Good',
0 => 'Poor',
);
$post_value = $_POST['state'];
$db_value = $values[$post_value];
// further validation: make sure the array key exists or use a default value
// further usage: build your HTML <options> with this array
However:
If you're going to do that, you're much better off storing the values as numbers and converting them to words when you display them (assuming the numbers do have some meaning). This also allows you to localize by providing translations.
Response to comments:
I would recommend a rating system, like 1 through 5, and calculate your price modifications internally - not directly from the user input or from a hardcoded value (in the database). This allows you to tweak the price changes from within your app, rather than from database values that were created at an earlier time, like if you decide an "Excellent" condition warrants an increase of 11 rather than 10 - unless you specifically want the prices "locked in" permanently at the time the product was posted.
Whatever you do, make sure to validate the input - I can't think of any good reason to use direct user input to calculate prices - it should be done internally based on product ids, and any other conditions. HTML source can be modified on-the-fly to post values you didn't expect from the dropdown.

You can't get it via the HTML form. But you can still do a server side that would map the values to the appropriate condition.
You can use a switch statement or an if statement to map them.
if(value == 10){
$condition = 'Excellent';
} else {//....}

Related

SQL query in php with input from html dropdown

Ok so what I'm trying to do is make a query evaluation tool for a project. I get the user input as a php variable and use it in my query, so it's like the user is submitting the query. I am using mysqli
I'm currently doing this with my my query
$sql = "SELECT * FROM `idk` where `alias` = '".$s."'";
I get the values from the form below
$s = $_GET['val'];
<select name="selector" id = "selector">
<option value="">Select a criteria:</option>
<option value="0">id</option>
<option value="1">name</option>
<option value="2">email</option>
<option value="3">alias</option>
<option value="4">position</option>
I'm wondering if I can add user input for the where clause condition(=,!=) and get it like i get the value for the column instead of hard coding it.
Keep in mind that this is for a uni project and no one is going to use it or delete my database, but any security suggestions would be appreciated.
The shortest possible answer: yes. You can control everything. All you need to achieve this is add another choice element into your form that will let the user control the way values are compared. I'll use a simplified example.
If you have an input for the user's value:
<input type="number" name="age" value="" />
add a choice field before it:
<select name="age_comparison">
<option value="equal">equal to</option>
<option value="not_equal">not equal to</option>
<option value="less_than">less than</option>
<option value="greater_than">greater than</option>
</select>
<input type="number" name="age" value="" />
Note: the position isn't relevant for handling - at all. I just think it's a better user experience if users read your page just like they would a piece of text in real life. Meaning that when input comes later it will read as "age greater than X", which reads better than "age X, greater than", if you put the input first.
For the same reason (better user experience), I tend to label the options with something that reads more like a human, hence "equal to" instead of just "equal". But I omitted it from the option values since it doesn't add any valuable information to the code ("equal" tells the whole story as a parameter value).
Then, after your form is submitted, you can detect your user's choice and build the query string accordingly:
if (isset($_GET['age'])) {
$age = $_GET['age'];
}
if (isset($_GET['age_comparison'])) {
switch ($_GET['age_comparison']) {
case 'equal':
$ageComparison = '=';
break;
case 'not_equal':
$ageComparison = '!=';
break;
case 'less_than':
$ageComparison = '<';
break;
case 'greater_than':
$ageComparison = '>';
break;
}
}
// if we have all the parameters, we can query the database
if (isset($age) && isset($ageComparison)) {
// the following line is very unsafe - we'll be on that in a minute
$queryString = 'SELECT * FROM students WHERE age '.$ageComparison.$age;
...
Note: I used $_GET because you used it in your question. If you're going to have multiple parameters in your form, I suggest you rather use the post method and avoid having a whole bunch of parameters added to the url of your page. Your form values will be under the same keys, only in the $_POST variable. Plus, when you use post, it's enough to detect if the name of the submit is set - if it is, the rest of the inputs from the same form is guaranteed to be present as well. With get you have to check every parameter individually.
So there you have it. A query with variable comparison operators.
BUT
We're not done yet. There are some bad practices to shed away and some good practices to pick up on the way.
First and foremost, never build queries by directly inserting parameters:
$sql = "SELECT * FROM `idk` where `alias` = '".$s."'";
That makes you wide open to SQL injection. You should use prepared statements instead. Prepared statements have built-in protection mechanisms and also take care of all your quoting needs (meaning you don't have to manually put uote marks around parameters that are strings). So you do it like this:
// the question mark means we'll be adding a parameter in that position
$queryString = 'SELECT * FROM students WHERE age '.$ageComparison.' ?';
// here I assume you have mysqli statement ready
// you can see an example about creating one in the link about prepared statements
$statement->prepare($queryString);
$statement->bindParam('i', $age);
You might say "But wait a minute! You just added the comparison operator directly! Isn't that dangerous?" - no, because it didn't come directly from the user. We decided its value in the switch statement, meaning we took user's input (which might be compromised) and turned it into a value that we control. The user can't decide what comes out of the switch statement, we can. Hence, it's safe to directly concatenate it into the query string because we know we've defined some safe values.
Speaking of the switch statement, there's an improvement to be made there, too. What if we add another option in the select, but we forget to add it in the switch statement? Or a malicious user compromises the value of the option being sent? We will end up with an error, since then no cases in the switch will be matched (a case for a value outside of the 4 we put there is not defined) and thus the variable $ageComparison will never be created and we'll never execute the query, because our if condition will fail. So how do we fix it? We add a default case (default executes when none of the cases are matched):
// remainder of statement cut for length
...
case 'greater_than':
$queryComparison = '>';
break;
default:
throw new Exception('Unsupported value for age comparison: '.$ageComparison);
}
Exceptions halt execution when not handled (the proper term is caught), but I'll leave it to you if you wish to explore that topic on your own (seems a bit much for a beginner, plus there's quite a bit of text here already).

Mysql INSERT SET type

Sorry for my English but it is not my native language.
I have created a user interface to insert data to MySQL. Everything except one thing is ok but when I want to read data from multiple checkboxes and write them to SET type in MySQL it just doesn't work. I have tried to find the answer but after 4 hours I can't find it or I don't understand it.
http://jyxo.info/uploads/21/21b104df77f6ca723bb708d8d0549af5430e8e91.jpg
dobaVyskytu is SET type and there are in with month you can find mushroom(my tema is online atlas of mushrooms)
in user interfacei have 12 checkbox for 12 month.
http://jyxo.info/uploads/FD/fd548760b155307dfa677ada7c4be4996abf7b93.png
In dobavyskytu i need to have multiple select and that is reason why i use $doba +=
if(isset($_POST["Leden"]))
{
$doba += "Leden";
}
if(isset($_POST["Únor"]))
{
$doba += "Únor";
}
if(isset($_POST["Březen"]))
{
$doba += "Březen";
}
Db::query("INSERT INTO houby(nazev,dobaVyskytu,mistoVyskytu,popis,jedovatost,img)VALUES(?,?,?,?,?,?)",$nazev,$doba,$misto,$popis,$jedovatost,$foto);
Thank you all for reading and for help because it works now.
For strings in PHP, it uses . as concatanation not +, so
$doba .= "Leden";
Edit:
For a better way of doing this, you should try something like...
$options = [];
if(isset($_POST["Leden"]))
{
$options[] = "Leden";
}
if(isset($_POST["Únor"]))
{
$options[] = "Únor";
}
...
$doba = implode(',', $options);
As this will give you something like Leden,Únor
My hypotheses are:
$doba is the variable you want to insert in your SET type column (I translated and it seems the values you put as example in your question is Slovak for "January", "February", "March" -- I suppose there could be more).
I suppose that your SET type column is "dobaVyskytu" and that you created it correctly in MySQL by including all the possible values in the column definition.
(Your question update seem to confirm my hypotheses!)
First, when you want to insert multiple values in a SET type column in MySQL, the string value has to be separated with commas.
With the code I see, you can end up with that string "LedenÚnorBřezen" (I suppose you use += for string concatenation, but you should really use .= like Nigel Ren mentionned). You really want to end up with a string like "Leden,Únor,Březen" if all the 3 values you show are checked in your form.
See here for how to handle SET type in MySQL:
https://dev.mysql.com/doc/refman/5.7/en/set.html
Since you do not know if you will end up with 0 or multiple values for that column, I would suggest to make $doba an array.
$doba = array(); // depending on your PHP version, you can also write $doba = [];
After, you can add your values this way (the syntax $array[] = 'value' will apprend a value to the array):
$doba[] = "Leden";
$doba[] = "Únor";
$doba[] = "Březen";
Then, before inserting it, you can convert the array to a string with the values separated by commas that way:
$csvDoba = implode(',', $doba);
Then use $csvDoba instead of $doba in your Db::query() line.
After you get this working, here are more things you can look for to improve your code:
You can also take advantage PHP magic by naming your form checkbox with a special name to avoid repeating yourself.
For example, you can name all your checkboxes with the name "doba[]", and if (isset($_POST["doba"]), it will already be an array with all the checked values! But beware, if no value is checked, it won't be set. That way, you will avoid doing an if condition for each of your checkbox.
You can do something like this in your code to retrieve the value:
$doba = isset($_POST['doba']) ? (array) $_POST['doba'] : array();
What this do?
If any checkboxes named "doba[]" is checked, then you will retrieve them and make sure the value you retrieve is of type array, the "(array)" part for the value to be an array even if it was not (e.g., an error or someone trying to hack your form). Else you will return an empty array (as no choices has been put).
If you are not familar with this syntax, do a searcch for "ternary operator".
You will of course want to do some validation of your values if not already done
You might look to put the values in another table instead of using the "SET type", but that is up to you and at this stade you probably still have a couple stuff to learn, so I don't want to flood you with too much info. ;-)

Select a text field from mysql in php

usersim interested how do i select a text field form my mysql database, i have a table named users with a text field called "profile_fields" where addition user info is stored. How do i access it in php and make delete it? I want to delete unvalidate people.
PHP code
<?php
//Working connection made before assigned as $connection
$time = time();
$query_unactive_users = "DELETE FROM needed WHERE profile_fields['valid_until'] < $time"; //deletes user if the current time value is higher then the expiring date to validate
mysqli_query($connection , $query_unactive_users);
mysqli_close($connection);
?>
In phpmyadmin the field shows (choosen from a random user row):
a:1:{s:11:"valid_until";i:1370695666;}
Is " ... WHERE profile_fields['valid_until'] ..." the correct way?
Anyway, here's a very fragile solution using your knowledge of the string structure and a bit of SUBSTRING madness:
DELETE FROM needed WHERE SUBSTRING(
profile_fields,
LOCATE('"valid_until";i:', profile_fields) + 16,
LOCATE(';}', profile_fields) - LOCATE('"valid_until";i:', profile_fields) - 16
) < UNIX_TIMESTAMP();
But notice that if you add another "virtual field" after 'valid_until', that will break...
You can't do it in a SQL command in a simple and clean way. However, the string 'a:1:{s:11:"valid_until";i:1370695666;}' is simply a serialized PHP array.
Do this test:
print_r(unserialize('a:1:{s:11:"valid_until";i:1370695666;}'));
The output will be:
Array ( [valid_until] => 1370695666 )
So, if you do the following, you can retrieve your valid_until value:
$arrayProfileData = unserialize('a:1:{s:11:"valid_until";i:1370695666;}');
$validUntil = arrayProfileData['valid_until'];
So, a solution would be to select ALL items in the table, do a foreach loop, unserialize each "profile_fields" field as above, check the timestamp, and store the primary key of each registry to be deleted, in a separate array. At the end of the loop, do a single DELETE operation on all primary keys you stored in the loop. To do that, use implode(',', $arrayPKs).
It's not a very direct route, and depending on the number of registers, it may not be slow, but it's reliable.
Consider rixo's comment: if you can, put the "valid_until" in a separate column. Serializing data can be good for storage of non-regular data, but never use it to store data which you may need to apply SQL filters later.

PHP: If statements unintentionally causing multiple MySQL columns to update?

I have a form on a page containing:
a text entry box named teachername
a text entry box named day (in the format YYYY-MM-DD)
a selection box named "resource" with the options [Library 1 or Library 2]
a selection box with the values [1,2,3 and 4] named block.
My mysql database has the fields:
- Teacher
Library1block1
Library1block2
Library1block3
etc.
The data from the html page is passed onto a php page meant to match the resource and block with the correct mysql field, and update the field so that the data from the text entry box "teachername" is inserted into it.
if ($_POST['resource']="Library 1" and $_POST['block']="1")
{mysql_query(
"UPDATE Resources
SET Teacher='yes', Library1block1='$_POST[teachername]'
WHERE Date='$_POST[day]'");}
if ($_POST['resource']="Library 1" and $_POST['block']="2")
{mysql_query(
"UPDATE Resources
SET Teacher='yes', Library1block2='$_POST[teachername]'
WHERE Date='$_POST[day]'");}
Expected:
- Enter "Mr. Smith" into teachername text entry field, select "Library 1" and "1" within the selection menu, and enter "2012-03-16" in the text entry field named day
Data is stored and passed along to the php script
an if statement updates the database record containing the field matched by the "resource"
field and "block" field (library1b1, library1b2, etc) for the date entered in the day text field
the field is updated, and the subsequent if statements check to match up the entered data with the correct mysql field
Result:
All fields (not just the specified field) are updated according to the first if statement.
EX: Entering in "Mr. Smith" for teachername, selecting "Library 1", selecting "1" for the block, and entering "2012-03-16" for the date does not update only the Library1block1 field, but it also updates the Library1block2 and library2block1 fields.
The mysql statement, when entered directly into a mysql terminal, updates the singular field correctly, but the usage of this php code results in multiple updated rows.
Help please?
You are making a common mistake of using the assignment operator (=) rather than the equality operator (==). On lines that look like this:
if($_POST['resource']="Library 1")
Change them to use the comparison operator:
if($_POST['resource'] == "Library 1")
The folks who have given answers have done a good job, but I would like to add one little trick that I like to use sometimes (depending on the language, etc.)
Usually you will write an if statement as something like
if ( $var == 1 ) { do_stuff( $var ) }; //or whatever
This following simple little trick has made this potential mistake almost impossible for me to make (esp. with php).
Just switch the two around.
So instead of the usual:
if ( $var == 1 ) { do_stuff( $var ) }; //or whatever
Try this instead whenever you can:
if ( 1 == $var ) { do_stuff( $var ) }; //or whatever
I'm pretty sure php 5.2+ hasn't changed to the point that it no longer works, but even if you make the mortal mistake of using a single equals sign it should still work because you can't assign a value to a constant (numbers are constant values, right?).
I believe this relies on php's behavior of always processing code from left to right:
if ( 1 = $var ) { do_stuff( $var ) }; //or whatever
And you're golden! Since I started doing this over 5 years ago I have never run into this problem again. 1 is always 1, no matter what you do. This is a good way of thinking through your conditionals, loops, etc. in php.
The beauty of this is in its mind smacking simplicity. "$var" can be lots of things, but the number 1 is always the number 1. I'm sure this doesn't work for all languages, but for php, it's one I use a lot, and it's apparently a good habit anyway to structure your code this way.
You should use two equal signs like this in you if statements to compare values:
$_POST['resource']=="Library 1"
This will check if $_POST['resource'] equals (==) Library 1
A single equal sign assigns Library 1 to $_POST['resource']
You may check Comparison Operators on php.net for more information:
http://php.net/manual/en/language.operators.comparison.php
Edit:
You should also use mysql_real_escape_string() for user input value such as $_POST:
if ($_POST['resource'] == "Library 1" and $_POST['block'] == "2")
{
mysql_query(
"UPDATE Resources
SET
Teacher='yes',
Library1block1='".mysql_real_escape_string($_POST['teachername'])."'
WHERE
Date='".mysql_real_escape_string($_POST['day'])."'"
);
}

php+mysql : increase a cell's value without checking it?

I've got a form with checkboxes set to bitwise values (CB1=1,CB2=2,CB3=4,CB4=8), and I want to store their sum in a single cell (to avoid having empty fields). The checkboxes have the same name but different values, and the data is sent to the processing php script as a serialised string, ie name=value&name=value2&name3=value3&name=&name=value5
Currently I can separate the string and get the values into the proper cells rather efficiently/easily. But, I'm wondering if there is a way to insert the first value into the cell then add subsequent values to the same cell. I imagine it would look something like this:
foreach ( $qaPairs as $pair ) {
list($question , $answer) = explode('=', $pair);
// ^ splits Q1=A1 into $question=Q1 and $answer=A1
// this mysql_query is a modified version of what I'm currently using
mysql_query("UPDATE $table SET `$question`=`$question`+'$answer' WHERE `key`='$key';") or die(mysql_error());
// $question is also the name of the column/field
} // end foreach
I dunno if it makes a difference, but: there are other datatypes (besides bitwise integers, such as text) and other form types (like textfields).
P.S. I would rather not have to somehow check if there are multiple instances of the same name and then do addition.
P.P.S. I got the UPDATE idea from this question: MySQL Batch increase value?, and I tried it out, but it didn't update null values (which I need it to do).
Thanks in advance!

Categories