【问题标题】:Wordpress - generate random unique number using atomic operation and update databaseWordpress - 使用原子操作生成随机唯一数字并更新数据库
【发布时间】:2019-06-10 09:01:52
【问题描述】:

我创建了一个名为 wp_tickets 的表,其中包含从我的 wordpress 帖子中设置的自定义字段生成的一系列票号。表中的列是'id', 'ticket_id', 'lottery_id''used'

当客户在我的网站上购买产品时,我试图生成一个随机的唯一编号。

例如,如果客户订购了五件相同的产品。它需要根据产品元字段中设置的字段'maximum_entries' 生成5 个随机唯一数字,然后在wp_tickets 表中将这些数字标记为“已使用”。

我需要这是一个原子操作,这样如果客户同时订购,他们就不能拥有相同的号码。

到目前为止,我已经创建了一个要在 woocommerce_order_status_processing 钩子上调用的函数,它遍历购物车中的每个产品并获取产品数量。然后在调用 array_rand 之前,我使用 range 函数将其转换为数字数组。

然后我在$wpdb 更新函数中使用$ticketallocated

我遇到的问题是,如果正在生成的号码已经在表格中标记为“已使用”,那么它不会循环回到顶部并重试。我需要以某种方式设置一个 if/else 语句,因此如果生成的随机数是 5,并且数据库中已经有一个 5 为“已使用”,那么它将尝试不同的数字。

add_action('acf/save_post', 'my_acf_save_post', 20);
function my_acf_save_post( $post_id ) {
    global $wpdb;
    $qty = get_field('maximum_entries');
    $array = range(1, $qty);

    foreach ($array as $ticket) {
     $wpdb->insert('wp_tickets', array(
         'ticket_number' => $ticket,
         'lottery_id' => $post_id,
     ));
    }
}


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
            "
);     

}             

}

【问题讨论】:

  • 虽然可以使用数据库执行此操作,但我建议您使用适当的 fifio 队列,例如 beanstalkd,并使用唯一的随机票号预先填充它。
  • 嗨@Geoffrey 我想我现在已经设法让它在数据库中工作。与 fifio 队列相比,使用数据库的缺点是什么?
  • @Geoffrey 你认为使用数据库可能会导致问题吗?
  • 如果你有一个真正的原子操作应该没问题,只是它的性能不如专用的先进先出队列。此外,由于您有一个可行的解决方案,请发布您对此问题的答案并接受它。
  • 嗨@Geoffrey,我提供了对我有用的解决方案。如果您能看一下,看看我所做的是否是“真正的原子操作”,那就太好了。我怀疑这不是我在调用多个函数?

标签: php sql arrays wordpress foreach


【解决方案1】:

我设法通过创建两个函数让它工作。负责从wp_tickets 表中获取所有可用号码,其中used = 0lottery_id = $postID 从可用票号中返回一个随机数。

然后第二个函数负责使用get_available_numbers 函数生成的票号更新wp_tickets 表。

当客户订购时,这两个函数都在woocommerce_order_status_processing 钩子上执行,并且正在为他们购物车中的每件商品运行。

到目前为止,当我测试它时,它似乎工作。但是,很难说这在多个客户同时订购时的表现如何。

function get_available_numbers($postID) {
            global $wpdb;
                $result = $wpdb->get_results(
                    "
                    SELECT ticket_number
                    FROM wp_tickets
                    WHERE lottery_id = ".$postID." AND used = 0
                    ORDER BY RAND()
                    LIMIT 1
                    "
                    );
            return $result[0]->ticket_number;
}


function add_ticket_number($postID, $order_id, $number, $user_id) {
        global $wpdb;

        $wpdb->query(
            "
            UPDATE wp_tickets
            SET used = 1, order_id = ".$order_id.", user_id = ".$user_id."
            WHERE ticket_number= ".$number." AND lottery_id = ".$postID." AND used = 0
            "
                    );
}


for ( $i = 0; $i < $item_meta['_qty'][0]; $i++ ) {
                        $number = $this->get_available_numbers($product_id);
                        $this->add_ticket_number($product_id, $order_id, $number, $order->get_user_id());
                    }

更新

实际上,我通过在lottery_id 列上设置used=1 并将更新排序为随机且受1 限制,实际上已设法将其缩短为一个函数。

function add_ticket_number($postID, $order_id, $user_id) {
        global $wpdb;

        $wpdb->query(
            "
            UPDATE wp_tickets
            SET used = 1, order_id = ".$order_id.", user_id = ".$user_id."
            WHERE lottery_id = ".$postID." AND used = 0
                        ORDER BY RAND()
                        LIMIT 1
            "
                    );
}

【讨论】:

  • 第一种方式看起来不像真正的锁定,但第二种方式(更新)确实如此。我建议处理所有号码都已分配的情况
  • 嗨,大卫,对不起,您所说的“处理所有数字已分配的案例”是什么意思?
  • 如果WHERE 子句返回空会发生什么?
  • 谢谢大卫。这些数字基于每种产品设置的库存数量,因此我希望在分配所有数字后,无论如何不应允许客户完成购买。但是,我还没有彻底测试过,所以可能有一些我没有想到的东西。我的计划是在后端的现有网站上对此进行测试,这样客户就看不到任何数字并查看它的性能。除非有办法在 Wordpress 上以编程方式测试多个订单?
  • 我对Wordpress不太熟悉,说有没有这样的方式(测试多个订单)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多