Background
Hello, I\'m developing an experimental/educational tool in PHP and MySQL. I\'m new to SQL, but I want to do things the right way from th
You're doing so much right that I actually feel guilty pointing out that you're doing something wrong! :)
You can only use prepared statements to parameterise field values—not SQL identifiers such as column or table names. Therefore you won't be able to pass A.x, B.z etc. into your JOIN criteria by way of prepared statement parameters: you must instead do what feels terribly wrong and directly concatenate them into your SQL string.
However, all is not lost. In some vague order of preference, you can:
Present the user with an option list, from which you subsequently reassemble the SQL:
Then your form handler:
switch ($_POST['join_a']) {
case 1: $acol = 'x'; break;
case 2: $acol = 'y'; break;
default: die('Invalid input');
}
switch ($_POST['join_b']) {
case 1: $bcol = 'z'; break;
case 2: $bcol = 'y'; break;
default: die('Invalid input');
}
$sql .= "FROM A JOIN B ON A.$acol = B.$bcol";
This approach has the advantage that, short of compromising PHP (in which case you'll have far bigger concerns than SQL injection), arbitrary SQL absolutely cannot find its way into your RDBMS.
Ensure the user input matches one of the expected values:
Then your form handler:
if (!in_array($_POST['join_a'], ['x', 'y'])
or !in_array($_POST['join_b'], ['z', 'y']))
die('Invalid input');
$sql .= "FROM A JOIN B ON A.$_POST[join_a] = B.$_POST[join_b]";
This approach relies on PHP's in_array function for safety (and also exposes to the user your underlying column names, but given your application I doubt that's a concern).
Perform some input cleansing, such as:
mb_regex_encoding($charset); // charset of database connection
$sql .= 'FROM A JOIN B ON A.`' . mb_ereg_replace('`', '``', $_POST['join_a']) . '`'
. ' = B.`' . mb_ereg_replace('`', '``', $_POST['join_b']) . '`'
Whilst we here quote the user input and replace any attempt by the user to escape from that quoting, this approach could be full of all sorts of flaws and vulnerabilities (in either PHP's mb_ereg_replace function or MySQL's handling of specially crafted strings within a quoted identifier).
It is far better if at all possible to use one of the above methods to avoid inserting user-defined strings into one's SQL altogether.