Php 使用PDO创建长插入SQL查询的最佳方法
考虑到我正在构建表单并将数据发布到PHP,我的典型插入查询如下所示:Php 使用PDO创建长插入SQL查询的最佳方法,php,mysql,sql,pdo,Php,Mysql,Sql,Pdo,考虑到我正在构建表单并将数据发布到PHP,我的典型插入查询如下所示: $sql = "INSERT INTO news (title, body) VALUES (?, ?)"; $stmt = $db->prepare($sql); $stmt->execute(array($_POST["title"], $_POST["body"])); $stmt->closeCursor(); $fields = array(
$sql = "INSERT INTO news
(title, body)
VALUES (?, ?)";
$stmt = $db->prepare($sql);
$stmt->execute(array($_POST["title"], $_POST["body"]));
$stmt->closeCursor();
$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 ) ) )
对于一个小查询来说,这看起来很好,据我所知,这使我免受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有没有更干净的方法?使用bindParam方法,这是实现您期望的最简洁的方法。 这比用问号更容易理解。因此,代码将更易于维护 示例来自: 示例#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();
?>
希望这有帮助。我会这样做:
$sql = "INSERT INTO news
(title, body)
VALUES (?, ?)";
$stmt = $db->prepare($sql);
$stmt->execute(array($_POST["title"], $_POST["body"]));
$stmt->closeCursor();
$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()
的元素顺序现在不再重要了
不过,这假设
$\u POST
中的元素数量及其键与$sql
中的字段数量及其名称完全匹配。您可以动态创建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();
+1但我建议限制参数值:
$stmt->execute(array\u intersect\u key($\u POST,array\u flip($fields))
。结合Bill的输入,这看起来不错。虽然我的测试服务器没有运行PHP5.3,但我可以使用create_函数获得一个示例吗?(5.3以下的PHP版本不支持匿名函数),我尝试自己实现它,但我的PHP新手身份正在损害我@谢谢比尔,我已经添加了你的建议。@JoaoFerreira完成了。你现在应该很好了。create_函数的关键是在其参数周围使用单引号,否则将解析变量名。也许这就是为什么你不能让它工作的原因(只是一个疯狂的猜测)。这个答案太棒了。为我自己使用了一个通用的函数版本,非常方便。考虑一下,而不是手动构建这样的怪物。