注意:wpdb::Prepare调用不正确。Wpdb::Prepare()的查询参数必须有占位符

时间:2020-03-31 作者:Ateeq Rafeeq

//Get Services and save to database first.
for($i = 0; $i < count($_POST["wc_service_id"]); $i++) {
    $wc_service_id          = $_POST["wc_service_id"][$i];
    $wc_service_name        = $_POST["wc_service_name"][$i];

    $wc_service_code        = $_POST["wc_service_code"][$i];
    $wc_service_qty         = $_POST["wc_service_qty"][$i];
    $wc_service_price       = $_POST["wc_service_price"][$i];

    $insert_query =  "INSERT INTO `".$computer_repair_items."` VALUES(NULL, \'".$wc_service_name."\', \'services\', \'".$post_id."\')";
     $wpdb->query(
            $wpdb->prepare($insert_query)
    );
    $order_item_id = $wpdb->insert_id;


    $insert_query =  "INSERT INTO `".$computer_repair_items_meta."` 
                        VALUES(NULL, \'".$order_item_id."\', \'wc_service_code\', \'".$wc_service_code."\'), 
                        (NULL, \'".$order_item_id."\', \'wc_service_id\', \'".$wc_service_id."\'),
                        (NULL, \'".$order_item_id."\', \'wc_service_qty\', \'".$wc_service_qty."\'), 
                        (NULL, \'".$order_item_id."\', \'wc_service_price\', \'".$wc_service_price."\')";
    $wpdb->query(
            $wpdb->prepare($insert_query)
    );
}//Services Processed nicely
上面的代码运行得很好,唯一的问题是我得到了这个通知:调试模式打开时。我不应该收到任何通知。

注意:wpdb::prepare的调用不正确。wpdb::prepare()的查询参数必须有占位符。

有什么建议吗?我知道删除prepare(会解决问题。但如果您认为没有必要,我希望保留查询,请解释。

还可以为第一个查询添加%s,%d。但是对于第二个查询,如果我有3个值,该怎么办?

提前感谢您的回复。

2 个回复
最合适的回答,由SO网友:Sally CJ 整理而成

您不需要删除prepare(), 但你只需要把它做好

请检查$wpdb->prepare() reference 对于函数的语法等,但基本上不是(为了简洁而包装):

$insert_query = "INSERT INTO `".$computer_repair_items."`
    VALUES(NULL, \'".$wc_service_name."\', \'services\', \'".$post_id."\')";
$wpdb->query(
    $wpdb->prepare($insert_query)
);
你应该这样做:(假定$computer_repair_items 是有效的表名)

$insert_query = $wpdb->prepare(
    "INSERT INTO `$computer_repair_items` VALUES(NULL, %s, \'services\', %d)",
    $wc_service_name, // 2nd parameter; replaces the %s (first placeholder)
    $post_id          // 3rd parameter; replaces the %d (second placeholder)
);
$wpdb->query( $insert_query );
一、 e.必须将至少两个参数传递给$wpdb->prepare():

first parameter 是SQL命令,其格式应与PHP的sprintf() 函数,即使用占位符,如%s 对于字符串和%d 对于整数。

第二个参数应该是上述SQL命令中第一个占位符的替换值,即第一个参数。在我给出的例子中,第二个参数是$wc_service_name 该值替换%s 在SQL命令中<但是请注意,您应该not 将占位符用引号括起来,以便\'%s\'"%s" 例如,不正确且仅使用%s.

根据您的SQL命令,您还可以有第三个、第四个、第五个等参数,就像在我给出的示例中一样,其中有第三个参数,即$post_id 对于%d 占位符。

实际上single INSERT 操作,您可以简单地使用$wpdb->insert():

// Make sure you replace the column NAMES.
$wpdb->insert( $computer_repair_items, [
    \'column\'  => $wc_service_name,
    \'column2\' => \'services\',
    \'column3\' => $post_id,
] );
对于多个插入,可以尝试以下操作:

$insert_values = [];
foreach ( [
    [ \'wc_service_code\', $wc_service_code ],
    [ \'wc_service_id\', $wc_service_id ],
    [ \'wc_service_qty\', $wc_service_qty ],
    [ \'wc_service_price\', $wc_service_price ],
] as $row ) {
    $insert_values[] = $wpdb->prepare( "(NULL, %d, %s, %s)",
        $order_item_id, $row[0], $row[1] );
}

$insert_query = "INSERT INTO `$computer_repair_items_meta`
    VALUES " . implode( \',\', $insert_values );
$wpdb->query( $insert_query );
或者直接打电话$wpdb->insert() 多次。。

SO网友:Jacob Peattie

您的代码非常不安全。

你没有使用$wpdb->prepare() 正确地你不能仅仅把它用在一个字符串上作为一个魔术补丁。这行代码中没有任何内容可以保护您免受SQL注入攻击,因为您从$_POST 并将它们直接插入到SQL查询中:

"INSERT INTO `".$computer_repair_items."` VALUES(NULL, \'".$wc_service_name."\', \'services\', \'".$post_id."\')";
的全部要点$wpdb->prepare(), as documented, 是将变量安全地插入到SQL查询中。为此,您需要提供两件事:

带有占位符的SQL字符串,变量需要放在占位符中因此,不要:

$insert_query = "INSERT INTO `".$computer_repair_items."` VALUES(NULL, \'".$wc_service_name."\', \'services\', \'".$post_id."\')";
$wpdb->query(
    $wpdb->prepare($insert_query)
);
您需要执行以下操作:

$insert_query = "INSERT INTO `{$computer_repair_items}` VALUES( NULL, %s, \'services\', %s )";

$wpdb->query(
    $wpdb->prepare( $insert_query, $wc_service_name, $post_id );
);
请注意:

  • $wpdb->prepare() 无法从变量插入表名,但表名不应来自不安全的源。我假设您之前已经在代码中手动定义了%s 将替换为的安全转义版本$wc_service_name, 自动添加引号%s 将替换为的安全转义版本$post_id, 自动添加引号,因为这是您的原始代码所做的。如果该列实际上是整数列,则使用%d 而不是%s.$wpdb 实际上有a method 对于INSERT 自动为您准备查询的查询。对于我们的示例,您可以这样使用它:

    $wpdb->insert(
        $computer_repair_items,
        [
            $wc_service_name,
            $post_id,
        ],
        [
            \'%s\',
            \'%s\',
        ]
    );
    

相关推荐

归档页面的自定义帖子类型默认为index.php

我开发了一个自定义主题,其中包含一个名为events. 然而,出于某种原因,WP拒绝使用带有文件名的存档页面模板archive-events.php 根据WP的模板层次结构。WP始终默认为index.php 作为此帖子类型的模板。之前,我在WP中配置了一个页面,该页面被设置为slug/events/ 它现在是自定义post类型的slug。该页面现在已被删除,我不知道这是否是导致WP拒绝使用的问题archive-events.php 用于自定义帖子类型的存档列表。我试图修改并重新保存我的永久链接结构,但没有