You can't concatenate user input (or any other untrusted source) directly into an SQL query safely. That is the definition of an SQL injection vulnerability.
You also can't use query parameters for column names or other syntax.
But you can try to filter the untrusted input to make it trusted. Here's a demo:
$data = [];
$data['table']='mytable';
$data['column']='user_name';
$data['datatype']='tinyint(1)';
$rules = [
'table' => [
'filter' => FILTER_SANITIZE_SPECIAL_CHARS,
'flags' => FILTER_FLAG_STRIP_LOW|FILTER_FLAG_STRIP_HIGH|FILTER_FLAG_STRIP_BACKTICK
],
'column' => [
'filter' => FILTER_SANITIZE_SPECIAL_CHARS,
'flags' => FILTER_FLAG_STRIP_LOW|FILTER_FLAG_STRIP_HIGH|FILTER_FLAG_STRIP_BACKTICK
],
'datatype' => [
'filter' => FILTER_VALIDATE_REGEXP,
'options' => [
'regexp' => '/^(?:tinyint(?:\([[:digit:]]+\))|smallint(?:\([[:digit:]]+\))|int(?:\([[:digit]]+\)))|bigint(?:\([[:digit:]]+\))$/'
]
]
];
$inputs = filter_var_array($data, $rules);
$table = $inputs['table'];
$column = $inputs['column'];
$datatype = $inputs['datatype'];
$sql = "CREATE TABLE `$table` ( `$column` $datatype )";
I'll leave it as an exercise for you to build on this example to
- Recognize other data types besides the integers that I put into the regular expression for the data type.
- Process multiple user inputs for multiple columns.
- Use
filter_input_array()
instead of filter_var_array()
if you need this to read $_GET
for user input.