2012-02-16 1 views
3

私は、データベースに話しためのPDOについての質問があり、私は精通しています 例は次のとおりです。k/vペアと未知数のPDO?

$data = array('Cathy', '9 Dark and Twisty Road', 'Cardiff'); 

$STH = $DBH->("INSERT INTO folks (name, addr, city) values (?, ?, ?); 
$STH->execute($data); 

しかし、我々はK/Vのペアを持っていた場合、それは同じでしょうか? ala

$data = array('one'=>'Cathy', 'two'=>'9 Dark and Twisty Road', 'three'=>'Cardiff'); 

$STH = $DBH->("INSERT INTO folks (?, ?, ?) values (?, ?, ?); 
$STH->execute($data); 

値が不明確な場合はどうなりますか?

$data = array(range(0, rand(1,99)); 

$STH = $DBH->("INSERT INTO folks (/* how would you put stuff here? */) values (/* how would you put stuff here? */); 
$STH->execute($data); 

それがない以上、私はもっと混乱したまま....

は、誰かが上記の二つをk/Vのペアと、未知の数でどのように動作するかを見せてもらえますか?

答えて

0

準備文だけではない識別子で、リテラルで動作する多くの感謝を。したがって、識別子を入力して(適切にエスケープして)SQL文を構築する必要があります。

リテラルを正しくエスケープするのは難しいですが、 PDOはリテラルエスケープのためのメソッドを提供せず、リテラルをエスケープするMySQLのメソッド(`を使用)は、他のすべてのデータベースやANSI SQL標準とはまったく異なります。 See this question for more detail and for workarounds

我々は識別子をエスケープの問題を簡素化した場合、あなたはこのようなソリューションを使用することができます

// assuming mysql semantics 
function escape_sql_identifier($ident) { 
    if (preg_match('/[\x00`\\]/', $ident)) { 
     throw UnexpectedValueException("SQL identifier cannot have backticks, nulls, or backslashes: {$ident}"); 
    } 
    return '`'.$ident.'`'; 
} 

// returns a prepared statement and the positional parameter values 
function prepareinsert(PDO $pdo, $table, $assoc) { 
    $params = array_values($assoc); 
    $literals = array_map('escape_sql_identifier', array_keys($assoc)); 
    $sqltmpl = "INSERT INTO %s (%s) VALUES (%s)"; 
    $sql = sprintf($sqltmpl, escape_sql_identifier($table), implode(',',$literals), implode(',', array_fill(0,count($literals),'?')); 
    return array($pdo->prepare($sql), $params); 
} 

function prefixkeys($arr) { 
    $prefixed = array(); 
    for ($arr as $k=>$v) { 
     $prefixed[':'.$k] = $v; 
    } 
    return $prefixed; 
} 

// returns a prepared statement with named parameters 
// this is less safe because the parameter names (keys) may be vulnerable to sql injection 
// In both circumstances make sure you do not trust column names given through user input! 
function prepareinsert_named(PDO $pdo, $table, $assoc) { 
    $params = prefixkeys($assoc); 
    $literals = array_map('escape_sql_identifier', array_keys($assoc)); 
    $sqltmpl = "INSERT INTO %s (%s) VALUES (%s)"; 
    $sql = sprintf($sqltmpl, escape_sql_identifier($table), implode(',',$literals), implode(', ', array_keys($params))); 
    return array($pdo->prepare($sql), $params); 
} 
+0

を、あなたは '$のassoc'が何のためにあるのか、その使用方法を説明していただけますか? – ehime

+0

'$ assoc'はあなたの投稿に記述する' 'columnname '=>' columnvalue''の連想配列です! –

+0

さて、私は '$ pdo'が何であるか混乱しています。私は(何らかの愚かな理由で)エントリの配列ポイントであると思っていました – ehime

2

あなたが使用する必要はありませんか?バインディングプレースホルダとして、:名前と連想配列を使用できます。連想配列をバインディングリストとして渡すことができ、PDOは配列のキーと:binding_namesを一致させるようになります。名前/値ペアの未知の数を処理します

$data = array('one'=>'Cathy', 'two'=>'9 Dark and Twisty Road', 'three'=>'Cardiff'); 
$fields = array_keys($data); 
$field_str = '`'.implode('`,`',$fields).'`'; 
$bind_vals = ':'.implode(',:',$fields); 
$sql = 'INSERT INTO tablename ('.$field_str.') VALUES ('.$bind_vals.')'; 
$sth = $dbh->prepare($sql); 
$sth->execute($data); 

:キーはデータベースのフィールドと一致している場合たとえば、連想配列で、あなたはこのような何かを行うことができます。挿入に使用するフィールド名が分からないことはありません。この例でも動作しますか?バインディングプレースホルダとして使用します。だから、名前ではなく、あなただけの繰り返しができます?

$bind_vals = str_repeat('?,', count($data)); 
$sql = 'INSERT INTO tablename ('.$field_str.') VALUES ('.$bind_vals.')'; 
関連する問題