2016-10-07 2 views
1

データをクリーンアップして変換しています(その部分は完了しています)、それをMySQLテーブルに挿入する必要があります。これまでPerlでこの種のことを行っていたのですが、処理の一環として、データを連想配列として構造化することが鍵となります。その方法では、単にキーをループし、名前付きプレースホルダと一致する値の両方のリストを生成するだけで、準備済みの文を作成するのは簡単です。PHP連想配列をPDOプリペアドステートメントにマッピングする

しかし、私はこの作業を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風味のフレーズを紹介してくれたら、私はそれを感謝します。

+3

INSERT INTO foobar VALUES( '。': '。' implode( '、:'、$ fields) 'を表示しようとしましたか? ( '。': '。implode('、: '、$ fields)') '' –

+0

@E_p - よくできました!私はそれをエコーし​​ました - 全部ではなく、 "内側"の部分 - それはOKと見えました。あなたはそうだ、それはクローズドパレンだった。 –

答えて

3

最終的なSQL文字列自体ではなく、SQLをフォーマットするPHPコードを見ているときに、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 

今、それはあなたがそのINSERT文の最後に決算)を忘れてしまったことを確認することは非常に簡単です!

また、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); 
} 

ヒント:

  • が一度にクエリを準備し、挿入したいデータの行ごとに準備された文を再利用ここで私はこのコードを記述します方法です。
  • データ値の配列を引数として​​に渡します。これはbindParam()を使用するより簡単です。
  • データが連想配列ではなく単純配列にある場合、名前付きパラメータプレースホルダの代わりに位置パラメータプレースホルダ(?)を使用します。
+1

美しい - 私が探していたもの。ありがとう、ビル! @E_pは、私がパレンを見逃してしまったという事実を発見しましたが、あなたの答えには、それを読んだときに意味をなさないものも含まれていました(私のコードではありませんでした)。 –

+0

あなたが誰かに展開するとき、完璧(クレジットなし)の答えが完璧であることを確認してください。 '$ sql =" INSERT INTO foobar($ columns)VALUES($プレースホルダ) ";' '$ sql = sprintf(" INSERT INTO foobar(%s)VALUES(%s) "、$ columns、$プレースホルダ)でなければなりません。 ' –

+0

私はBillの書き換えに同意します。しかし、名前付きプレースホルダを使うことは、 '?' 'よりも追跡がずっと簡単です。私はMySQLi_とPDOの両方のプリペアドステートメントを使用していますが、PDOでは名前のプレースホルダを99%の時間使用します。それは私だけです;-) –