I have a multiple select field designed as below:
First and foremost:
Please, don't use mysql_* functions in new code. They are no longer maintained and are officially deprecated. See the red box? Learn about prepared statements instead, and use PDO, or MySQLi - this article will help you decide which. If you choose PDO, here is a good tutorial.
It has become more important than ever that you follow this advice, ext/MySQL has now been deprecated and using it will emit E_DEPRECATED
errors beginning with PHP 5.5, it will one day be completely removed from core language. Having said that, the following applies to all drivers for all databases.
For the rest of this explanation I shall assume that you are unable to use MySQLi or PDO for some reason (note that the only satisfactory reason here is that they are not available, "I don't know how to use them" is not an excuse) and that you are forced to use ext/MySQL. If you are able to use either of the newer drivers, then you are able to use prepared statements, and none of this applies. So, with that in mind...
Next let's take a look at what is wrong with the previous answer. This centres around escaping user input. It uses mysql_real_escape_string()
is a way that really makes no sense whatsoever. This should be used for escaping a single string literal, and absolutely nothing else, ever. It cannot be used to effectively escape numbers, and it cannot be used to escaped parts of SQL that are not only values.
The following two code snippets show the correct way to do this, dependent on what the data is and, crucially, its type.
Here's what we would do if the values are strings (usually a CHAR
or VARCHAR
field):
// First create an array of individually escaped values with quotes added
$deds = array();
foreach ($_POST['deductions'] as $ded) {
$deds[] = "'".mysql_real_escape_string($ded)."'";
}
// Now join them together in an SQL syntax
$deds_joined = join('), (', $deds);
// Now they can safely be used in the query
$query = "INSERT INTO mytable (deduction) VALUES ($deds_joined)";
But often in this scenario, the values would simply be numbers, and in this case all we need to do is ensure that PHP is representing them with the correct data type, since they will be automatically safe when they are converted back to strings to be used in the query:
// First convert the array values to integers
$deds = array();
foreach ($_POST['deductions'] as $ded) {
$deds[] = (int) $ded;
}
// Now join them together in an SQL syntax
$deds_joined = join('), (', $deds);
// Now they can safely be used in the query
$query = "INSERT INTO mytable (deduction) VALUES ($deds_joined)";
This code obviously assumes that the data is of an integer type, floats can easily be handled by simply changing the (int)
cast to (float)
.
It's also worth noting that the string approach can be safely and successfully used for numeric values as well, because MySQL will also convert the values to the correct type. But in general it is better and more efficient to pass the data in with the correct type representation within the query.