mysql — Отображение ассоциативных массивов PHP в подготовленные операторы PDO

Я делаю некоторую очистку и преобразование данных (эта часть выполнена, вот так), и мне нужно вставить его в таблицу MySQL. Сделав подобные вещи в Perl ранее, я предположил, что, как часть обработки, для меня будет иметь смысл структурировать данные как ассоциативный массив с ключами, совпадающими с именами полей, в которые мне нужно загрузить их — таким образом, было бы легко создать подготовленный оператор, просто зацикливая ключи и создавая список как именованных заполнителей, так и соответствующих значений.

Тем не менее, я не могу заставить это работать в PHP / PDO. Тестовый код:

$x = <<<EOD
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
4 4 4 4 4
EOD;

$fields = array('name', 'job', 'wallet_size', 'inseam', 'pet_name');
foreach(explode("\n", $x) as $line){
$data = array_combine($fields, explode(' ', $line));

# print_r($data);

$stmt = $dbh->prepare('INSERT INTO foobar VALUES('.':'.implode(', :', $fields));

foreach($fields as $field){
$stmt->bindParam(':'.$field, $data[$field]);
}
$stmt->execute();
}

Честно говоря, это кажется слишком … изящным и хакерским для работы — и это не так.

Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1' in tst.php:24

Там является правильный способ сделать это, верно? Я был бы признателен, если бы кто-нибудь познакомил меня с соответствующей формулировкой на PHP.

1

Решение

Трудно отлаживать SQL, когда вы смотрите на код PHP, который форматирует SQL, вместо самой конечной строки SQL. Я предлагаю вам всегда создавать строковую переменную, чтобы вы могли выводить ее во время отладки.

$sql = 'INSERT INTO foobar VALUES('.':'.implode(', :', $fields);
echo "$sql\n";
$stmt = $dbh->prepare($sql);

Выходы:

INSERT INTO foobar VALUES(:name, :job, :wallet_size, :inseam, :pet_name

Теперь очень легко увидеть, что вы забыли закрытие ) в конце этого заявления вставки!

Кроме того, ваше использование PDO сложнее, чем нужно. Вам не нужно использовать именованные параметры. Вам не нужно использовать bindParam(), Вот как бы я написал этот код:

$fields = array('name', 'job', 'wallet_size', 'inseam', 'pet_name');

$columns = implode(',', $fields);
$placeholders = implode(',', array_fill(1, count($fields), '?'));
$sql = "INSERT INTO foobar ($columns) VALUES ($placeholders)";
echo "$sql\n"; // use this during debugging
$stmt = $dbh->prepare($sql);

foreach(explode("\n", $x) as $line){
$param_values = explode(' ', $line);
$stmt->execute($param_values);
}

Подсказки:

  • Подготовьте запрос один раз и повторно используйте подготовленный оператор для каждой строки данных, которые вы хотите вставить.
  • Передать массив значений данных в качестве аргумента execute(), Это проще чем использовать bindParam(),
  • Использовать позиционные параметры-заполнители (?) вместо заполнителей именованных параметров, когда ваши данные находятся в простом массиве вместо ассоциативного массива.
3

Другие решения

Других решений пока нет …