php 带IN()条件的WordPress预准备语句

gijlo24d  于 2022-10-30  发布在  PHP
关注(0)|答案(7)|浏览(155)

我在一个字符串中有三个值,如下所示:

$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中正确地实现一个具有多个值的预准备语句?

ctzwtxfj

ctzwtxfj1#

请尝试以下代码:

// 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;
8fsztsew

8fsztsew2#

WordPress已经有了一个用于此目的的函数,请参见esc_sql()。下面是此函数的定义:
对MySQL查询中使用的数据进行转义。通常应使用wpdb::prepare()准备查询。有时,点转义是必需的或有用的。一个示例是准备在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 . ")"
s4chpxco

s4chpxco3#

功能:

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')

可能更有效,也可能不更有效,但它是可重用的。

rlcwz9us

rlcwz9us4#

下面是我为$wpdb清理IN (...)值的方法。
1.我使用了一个helper函数,它通过$wpdb->prepare()传递列表的每个值,以确保它被正确转义。
1.通过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 )
) );
vktxenjb

vktxenjb5#

第一个是一套现代的非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的helper方法语法更简单,因为变量绑定和查询执行由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_函数。
有用的参考资料:

kuarbcqp

kuarbcqp6#

我创建了一个小函数,它将从数组中为预处理语句生成占位符,例如(%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 ) . ')';
}

考虑问题中的示例,首先需要将值转换为数组:
第一个

qltillow

qltillow7#

prepare函数还将array作为第二个参数。
您可以尝试如下转换$villes

当前

<?php
$villes = '"paris","fes","rabat"';
?

将其更改为

<?php
$villes = array("paris","fes","rabat");
?>

现在,尝试将$villes传递给prepare函数,看看它是否有效。希望它能有所帮助。

相关问题