Как я уже сказал в комментариях:
Ну, у вас есть 14 ?
и 11 s
по моим подсчетам. ИЛИ sssssssssss
и ??????????????
Что, как известно большинству из нас, приведет к ошибке, поскольку число заполнителей не соответствует вашим значениям
Если вы можете поместить свои данные в массив, вы можете использовать этот массив для построения вашего запроса.
if($sql = $conn->prepare("INSERT INTO `asset`(`id`, `assetName`, `grp`, `Descrip`, `enteredValue`, `depreciationRate`, `entrydate`, `availability`, `enteredBy`, `updatedOn`, `isPeriodic`, `assetType`, `Frequency`, `ExitDate`) VALUES (".implode(',', array_fill(0,count($data), '?')).")")){
$sql->bind_param(str_repeat('s', count($data)),...$data);
Пройдемся, подумал немного
По сути, вы можете создавать свои аргументы такой же длины, что и $data
, с помощью следующих двух частей кода:
implode(',', array_fill(0,count($data), '?')) //implode "?" with "," equal to the length of data
str_repeat('s', count($data)) //create 's' equal to the length of data
Тогда здесь происходит настоящее волшебство с ...
«variadic» (аргументы переменной длины):
$sql->bind_param(str_repeat('s', count($data)),...$data);
В PHP v5.6+
вы можете просто ввести данные, используя ...
in, и это раскрутит их для вас. Или, другими словами, поместите каждый элемент массива в качестве нового аргумента.
Для полей (столбцов)
Если вы тоже хотите заполнить поля, это немного сложнее. Вы должны быть осторожны с тем, что в них, если вы помещаете эти данные непосредственно в SQL. Например, пользователь может редактировать ключи, используемые в запросе $_POST
, таким образом, чтобы сделать SQLInjection, если вы просто объедините ключи Post в SQL.
Один из самых простых способов решить эту проблему - создать белый список полей, таких как (сопоставленных с именами столбцов):
//all allowed column names for this query (case sensitive)
$whitelist = ["id", "assetName", ...];
Вы можете использовать array_intersect_key
, чтобы сохранить только те данные, которые вам нужны для запроса (при условии, что данные соответствуют ключам). Ключи теперь можно будет безопасно использовать в запросе, так как они должны совпадать с ключом $whitelist
.
//remove unknown keys form input data (~ retain only known ones)
//array_flip($whitelist) = ["id"=>0, "assetName"=>1, ...];
$data = array_intersect_key($_POST, array_flip($whitelist));
if($sql = $conn->prepare("INSERT INTO `asset`(`".implode("`,`", array_keys($data))."`)VALUES(".implode(',', array_fill(0,count($data), '?')).")".)){
$sql->bind_param(str_repeat('s', count($data)),...$data);
Другие вещи
Единственное, на что это не распространяется, это если вы хотите, чтобы все поля в $whitelist
присутствовали всегда. Вы можете решить эту проблему с помощью проверки входящих данных или объединить несколько пустых полей, чтобы убедиться, что все данные присутствуют.
$default = array_fill_keys($whitelist, ''); //["id"=>"", "assetName"=>"", ...] ~ create empty "default" row
//$default['updatedOn'] = date('Y-m-d'); //you can also manually set a value
$data = array_intersect_key(
array_merge(
$default,
$_POST //["id"=>"1", ...] ~ missing assetName
), array_flip($whitelist)); //-> ["id"=>"1","assetName"=>""]
Ключи заполнения массива (аналогично предыдущему заполнению массива) принимают список ключей и добавляют значения для каждого из них. Таким образом, мы получаем массив, ключами которого являются значения $whitelist
и пустую строку для каждого значения элемента. Я называю это строкой по умолчанию.
Затем мы объединяем это с нашими исходными данными. Данные в первом массиве будут перезаписаны любыми данными с соответствующими ключами для второго массива ($_POST
в моем примере). Таким образом, если ключ присутствует, например, id
в приведенном выше примере, он перезаписывает пустой.
Все, что не перезаписано, сохраняет пустое значение из строки по умолчанию, которую мы сделали. Затем ключ пересечения массива удаляет все лишнее, как раньше.
* PS Я не проверял ничего из этого, поэтому прошу прощения за любые синтаксические ошибки.
Наслаждайтесь!