Я делаю некоторую очистку и преобразование данных (эта часть выполнена, вот так), и мне нужно вставить его в таблицу 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.
Трудно отлаживать 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()
,?
) вместо заполнителей именованных параметров, когда ваши данные находятся в простом массиве вместо ассоциативного массива.Других решений пока нет …