我在这样的字符串中有三个值:
$villes = '"paris","fes","rabat"';
当我将其输入到这样的准备好的语句中时:
$sql = 'SELECT distinct telecopie FROM `comptage_fax` WHERE `ville` IN(%s)';
$query = $wpdb->prepare($sql, $villes);
echo $query;
显示:
SELECT distinct telecopie FROM `comptage_fax` WHERE `ville` IN('"CHAPELLE VIVIERS ","LE MANS ","QUEND"')
它不是将字符串写为三个单独的值 - 它只是一个双引号转义的字符串。
如何在WordPress中正确实现具有多个值的预准备语句?
试试这段代码:
// Create an array of the values to use in the list
$villes = array("paris", "fes", "rabat");
// Generate the SQL statement.
// The number of %s items is based on the length of the $villes array
$sql = "
SELECT DISTINCT telecopie
FROM `comptage_fax`
WHERE `ville` IN(".implode(', ', array_fill(0, count($villes), '%s')).")
";
// Call $wpdb->prepare passing the values of the array as separate arguments
$query = call_user_func_array(array($wpdb, 'prepare'), array_merge(array($sql), $villes));
echo $query;
-
implode()
-
array_fill()
-
call_user_func_array()
-
array_merge()
WordPress已经有一个用于此目的的功能,请参阅esc_sql((。以下是此函数的定义:
转义数据以在 MySQL 查询中使用。通常你应该使用 wpdb::p repare(( 准备查询。有时,斑点逃逸是必需的或有用的。一个示例是准备要在 IN 子句中使用的数组。
你可以像这样使用它:
$villes = ["paris", "fes", "rabat"];
$villes = array_map(function($v) {
return "'" . esc_sql($v) . "'";
}, $villes);
$villes = implode(',', $villes);
$query = "SELECT distinct telecopie FROM `comptage_fax` WHERE `ville` IN (" . $villes . ")"
函数:
function escape_array($arr){
global $wpdb;
$escaped = array();
foreach($arr as $k => $v){
if(is_numeric($v))
$escaped[] = $wpdb->prepare('%d', $v);
else
$escaped[] = $wpdb->prepare('%s', $v);
}
return implode(',', $escaped);
}
用法:
$arr = array('foo', 'bar', 1, 2, 'foo"bar', "bar'foo");
$query = "SELECT values
FROM table
WHERE column NOT IN (" . escape_array($arr) . ")";
echo $query;
结果:
SELECT values
FROM table
WHERE column NOT IN ('foo','bar',1,2,'foo"bar','bar'foo')
可能更有效,也可能不更有效,但它是可重用的。
$wpdb
IN (...)
值的方法。
- 我使用了一个帮助程序函数,该函数通过
$wpdb->prepare()
传递列表的每个值,以确保它被正确转义。 - 准备好的值列表通过
sprintf()
插入到 SQL 查询中。
帮助程序函数:
// Helper function that returns a fully sanitized value list.
function _prepare_in ( $values ) {
return implode( ',', array_map( function ( $value ) {
global $wpdb;
// Use the official prepare() function to sanitize the value.
return $wpdb->prepare( '%s', $value );
}, $values ) );
};
示例用法:
// Sample 1 - note that we use "sprintf()" to build the SQL query!
$status_cond = sprintf(
'post_status IN (%s)',
_prepare_in( $status )
);
$posts = $wpdb->get_col( "SELECT ID FROM $wpdb->posts WHERE $status_cond;" );
// Sample 2:
$posts = $wpdb->get_col( sprintf( "
SELECT ID
FROM $wpdb->posts
WHERE post_status IN (%s) AND post_type IN (%s)
;",
_prepare_in( $status ),
_prepare_in( $post_types )
) );
我创建了一个小函数,它将从数组中为预准备语句生成占位符,即类似 (%s,%d,%f)
,方便的是,它会根据数组的每个项目确切地知道要使用哪个占位符。
function generate_wpdb_prepare_placeholders_from_array( $array ) {
$placeholders = array_map( function ( $item ) {
return is_string( $item ) ? '%s' : ( is_float( $item ) ? '%f' : ( is_int( $item ) ? '%d' : '' ) );
}, $array );
return '(' . join( ',', $placeholders ) . ')';
}
考虑问题中的示例,首先您需要将值转换为数组:
$villes = array( "paris", "fes", "rabat" );
$in_str = generate_wpdb_prepare_placeholders_from_array( $villes );
$sql = "SELECT distinct telecopie FROM `comptage_fax` WHERE `ville` IN {$in_str}";
$query = $wpdb->prepare( $sql, $villes );
First 是一组现代的非 WordPress 技术,使用 mysqli 准备语句,数组中具有未知数量的值。 第二个片段将是WordPress的等效项。
假设输入数据的索引数组不受信任,可从$_GET['villes']
访问。 准备好的语句是现代标准,专业开发人员更喜欢旧的/不受信任的转义技术。 要遵循的代码段将返回具有数组中指定的ville
值之一的行。 如果数组未声明或为空,它将返回数据库表中的所有行。
原生 PHP 技术:
$sql = "SELECT DISTINCT telecopie FROM comptage_fax";
if (!empty($_GET['villes'])) {
$count = count($_GET['villes']);
$commaDelimitedPlaceholders = implode(',', array_fill(0, $count, '?'));
$stmt = $conn->prepare("$sql WHERE ville IN ($commaDelimitedPlaceholders)");
$stmt->bind_param(str_repeat('s', $count), ...$_GET['villes']);
$stmt->execute();
$result = $stmt->get_result();
} else {
$result = $conn->query($sql);
}
从这一点开始,您可以访问不同telecopie
值的行(从技术上讲,这是一个可迭代的结果集对象(,就像使用简单的foreach()
迭代关联数组的索引数组一样。
foreach ($result as $row) {
echo $row['telecopie'];
}
<小时 />使用WordPress的辅助方法,语法更简单,因为变量绑定和查询执行由get_results()
处理:
$sql = "SELECT DISTINCT telecopie FROM comptage_fax";
if (!empty($_GET['ville']) {
$commaDelimitedPlaceholders = implode(',', array_fill(0, count($_GET['ville']), '%s'));
$sql = $wpdb->prepare("$sql WHERE ville IN ($commaDelimitedPlaceholders)", $_GET['ville']);
}
$result = $wpdb->get_results($sql, ARRAY_A);
从这一点来看,$result
是关联数组的索引数组 - 特别是因为ARRAY_A
。 $result
不是第一个本机 PHP 代码段中的结果集对象。 这意味着您可以对数据使用经典循环语言构造函数或全套array_
函数。
有用的参考资料:
- https://developer.wordpress.org/reference/classes/wpdb/prepare/
- https://developer.wordpress.org/reference/classes/wpdb/get_results/
prepare
函数也将array
作为第二个参数。
您可以尝试像这样转换$villes
:
当前
<?php
$villes = '"paris","fes","rabat"';
?
将其更改为
<?php
$villes = array("paris","fes","rabat");
?>
现在,尝试将$villes
传递给准备函数,看看它是否有效。希望对您有所帮助。