首页 > 解决方案 > 生成一个唯一的随机数并根据用户订单存储它 - 同时处理请求?

问题描述

当客户在 Woocommerce 中完成订单并将其保存在数组中时,我使用下面的函数生成一个唯一的随机数,以便其他客户无法生成它。我在 woocommerce_order_processing 钩子上调用该函数。

我只是想知道这个解决方案有多防弹,以及它如何处理多个客户同时订购?它们是否有可能最终得到相同的数字,或者数据库是否能够足够快地返回正在使用的数字数组?

function add_lottery_ticket_number( $postId ) {
    if (metadata_exists('post', $postId, 'optionsToGive')) {
        $ticketOptions = get_post_meta( $postId, 'optionsToGive', true );
    } else {
        $lottery_max_tickets = get_post_meta( $postid, '_max_tickets', true );
        $ticketOptions = range(1, $lottery_max_tickets);
        shuffle($ticketOptions ); //random order of all number
    }
    $ticketAllocated = array_shift($ticketOptions); //take the first element
    update_post_meta( $postId, 'optionsToGive', $ticketOptions ); //update all the rest
    return $ticketAllocated;
}

for ( $i = 0; $i < $item_meta['_qty'][0]; $i++ ) {
    add_post_meta( $product_id, '_participant_id', $order->get_user_id() );
    $participants = get_post_meta( $product_id, '_lottery_participants_count', true ) ? get_post_meta( $product_id, '_lottery_participants_count', true ) : 0;
    update_post_meta( $product_id, '_lottery_participants_count', intval( $participants ) + 1 );
    $this->add_lottery_to_user_metafield( $product_id, $order->get_user_id() );
    $ticketnumber = $this->add_lottery_ticket_number($product_id);
    $log_ids[] = $this->log_participant( $product_id, $order->get_user_id(), $ticketnumber, $order_id, $item );
}

更新

我已经为所有要存储的票号创建了一个表格,其中包含您建议的“已使用”列。然后我在 foreach 语句中使用 $wpdb->query 函数并更新表。

但是,我不确定如何生成要在 WHERE ticket_number = $randomnumber' 中使用的随机数,并且它是唯一的,因此订购 5 张门票的一位客户将有 5 个不同的号码。那有意义吗?

add_action( 'woocommerce_order_status_processing', 'ektgn_meta_to_line_item', 20, 4 );

function ektgn_meta_to_line_item( $order_id )
{

    $order = wc_get_order($order_id);

    foreach( $order->get_items() as $item_id => $item_product ) {
        global $wpdb;

        $product_id = $item_product->get_product_id();
        $qty = get_field('maximum_entries', $product_id, true);
        $ticketOptions = range(1, $qty);
        $ticketAllocated = array_rand($ticketOptions, 1);

        $wpdb->query(
            "
            UPDATE wp_tickets 
            SET used = 1
            WHERE ticket_number= ".$ticketAllocated." AND lottery_id = ".$product_id." AND used = 0
            "
);     

}             

}

标签: phpsqlwordpresswoocommerce

解决方案


如果您每天只有几份订单,这很公平,但亚马逊肯定会以这种方式获得多张重复票。您正在寻找的是原子操作

可能的方式:

  • 为票号创建一个具有唯一列的 mysql 表。因为你不能两次插入一个数字...做 { INSERT INTO Tickets ($random_number) } while duplicate key error

  • 创建一个包含所有票证和“已使用”标志列的 mysql 表... do { UPDATE Tickets SET used=1 WHERE ticket_number=$random_number and used=0; } 而受影响的行 == 0;

  • 使用 redis 集... do { SADD Tickets $random_number } while result == 0


推荐阅读