5

フォームを作成してデータを PHP に投稿することを考えると、典型的な挿入クエリは次のようになります。

$sql = "INSERT INTO news
            (title, body) 
            VALUES (?, ?)";
$stmt = $db->prepare($sql);
$stmt->execute(array($_POST["title"], $_POST["body"]));
$stmt->closeCursor();

これは小さなクエリには問題ないように見えます。これにより、SQL インジェクションなどから安全に保つことができると理解しています。

しかし、かなり大きなフォームで作業する必要がある場合はどうすればよいでしょうか? 何かのようなもの...

$sql = "INSERT INTO ficha_item
    (titulo, tipo_produto, quantidade_peso, unidade_de_venda, 
    unidades_por_caixa, caixas_piso, pisos_palete, tipo_de_palete, 
    unidades_palete, caixas_palete, uni_diametro, uni_largura, 
    uni_profundidade, uni_altura, uni_peso_bruto_unidade, caixa_largura, 
    caixa_profundidade, caixa_altura, altura_palete, volume_unidade, 
    peso_caixa, peso_palete) 
    VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";

これらの疑問符をすべて数えるのは面倒だと思います。PDOでこれを行うためのよりクリーンな方法はありますか?

4

3 に答える 3

6

私はこのようなことをします:

$fields = array(
    'titulo', 
    'tipo_produto', 
    'quantidade_peso', 
    'unidade_de_venda', 
    'unidades_por_caixa', 
    'caixas_piso', 
    'pisos_palete', 
    'tipo_de_palete', 
    'unidades_palete', 
    'caixas_palete', 
    'uni_diametro', 
    'uni_largura', 
    'uni_profundidade', 
    'uni_altura', 
    'uni_peso_bruto_unidade', 
    'caixa_largura', 
    'caixa_profundidade', 
    'caixa_altura', 
    'altura_palete', 
    'volume_unidade', 
    'peso_caixa', 
    'peso_palete'
);
$sql = 'INSERT INTO ficha_item ( %s ) VALUES ( %s )';
// make a list of field names: titulo, tipo_produto /*, etc. */
$fieldsClause = implode( ', ', $fields );
// make a list of named parameters: :titulo, :tipo_produto /*, etc. */
$valuesClause = implode( ', ', array_map( function( $value ) { return ':' . $value; }, $fields ) );
// or, with create_function
$valuesClause = implode( ', ', array_map( create_function( '$value', 'return ":" . $value;' ), $fields ) );
$sql = sprintf( $sql, $fieldsClause, $valuesClause );

// $sql is now something similar to (formatted for display):
// INSERT INTO ficha_item
//     ( titulo, tipo_produto /*, etc. */ )
// VALUES
//     ( :titulo, :tipo_produto /*, etc. */ )

$stmt = $db->prepare($sql);

// if the keys in $_POST match with $fields, you can now simply pass $_POST here
$stmt->execute( $_POST );
// or, as per Bill Karwin's sound suggestion, with the intersection of $_POST
$stmt->execute( array_intersect_key( $_POST, array_flip( $fields ) ) )

$fieldsつまり、名前付きパラメーターを使用し、それらを配列に基づいて動的に生成します。名前付きパラメーターは厳密には必要ありませんが。たとえば、渡される要素の順序はもはや重要ではないため、物事を簡単にするのに役立ちますPDOStatement::execute()

ただし、これは、 の要素とそのキー$_POSTの数が、 のフィールドの数とその名前と正確に一致することを前提としています$sql

于 2012-12-30T22:48:45.717 に答える
2

SQL を動的に作成できます。

$allowed_fields = array(
    'titulo', 
    'tipo_produto', 
    'quantidade_peso', 
    'unidade_de_venda', 
    'unidades_por_caixa', 
    'caixas_piso', 
    'pisos_palete', 
    'tipo_de_palete', 
    'unidades_palete', 
    'caixas_palete', 
    'uni_diametro', 
    'uni_largura', 
    'uni_profundidade', 
    'uni_altura', 
    'uni_peso_bruto_unidade', 
    'caixa_largura', 
    'caixa_profundidade', 
    'caixa_altura', 
    'altura_palete', 
    'volume_unidade', 
    'peso_caixa', 
    'peso_palete'
);

$columns = "";
$values = "";
$values_arr = array();
foreach ( $_POST as $key=>$value )
{
    if ( !in_array($key, $allowed_fields) ) continue;
    $columns .= "$key, ";
    $values .= "?, ";
    $values_arr[] = $value;
}
// now remove trailing ", " from $columns and $values
$columns = rtrim($columns, ", ");
$values = rtrim($values, ", ");
// finish them
$sql = "INSERT INTO ficha_item($columns) VALUES($values)";
$stmt = $db->prepare($sql);
$stmt->execute($values_arr);
$stmt->closeCursor();
于 2012-12-30T23:45:46.797 に答える
1

bindParam メソッドを使用することは、期待どおりのことを行うための最も明確な方法です。これは疑問符よりもわかりやすいです。したがって、コードはより保守しやすくなります。

公式phpドキュメントの例:

例1 名前付きプレースホルダを使用してプリペアド ステートメントを実行する

<?php
/* Execute a prepared statement by         binding PHP variables */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
FROM fruit
WHERE calories < :calories AND colour = :colour');
$sth->bindParam(':calories', $calories, PDO::PARAM_INT);
$sth->bindParam(':colour', $colour, PDO::PARAM_STR, 12);
$sth->execute();
?>

お役に立てれば。

于 2012-12-30T22:31:53.820 に答える