检查客户是否已经在WooCommerce中购买了东西

时间:2016-08-10 13:00:46

标签: php wordpress woocommerce product orders

我想创建一个WooCommerce插件,为客户添加一些优惠(有购买历史记录)。

我如何检查用户之前买过的东西?

感谢。

8 个答案:

答案 0 :(得分:9)

  

更新:New updated improved, light and faster version HERE

  

可以创建条件函数,当客户已经至少有一个订单时,会返回true 完成

以下是此条件函数的代码:

function has_bought() {
    // Get all customer orders
    $customer_orders = get_posts( array(
        'numberposts' => -1,
        'meta_key'    => '_customer_user',
        'meta_value'  => get_current_user_id(),
        'post_type'   => 'shop_order', // WC orders post type
        'post_status' => 'wc-completed' // Only orders with status "completed"
    ) );

    // return "true" when customer has already at least one order (false if not)
   return count($customer_orders) > 0 ? true : false; 
}

此代码经过测试且有效。

此代码位于活动子主题或主题的function.php文件中,或插入php文件中。

USAGE (作为条件)

  • 您可以在之前已复制到活动子主题或主题 WooCommerce templates中使用它。
  • 在你的主题php文件中。
  • 在插件php文件中
  • 任何php函数或WordPress / WooCommerce。

参考

答案 1 :(得分:5)

这是一个更轻,更快的条件函数,如果客户已经进行了购买,它将返回true。

有一个可选参数$user_id,允许您指定已定义的用户ID:

function has_bought( $user_id = 0 ) {
    global $wpdb;
    $customer_id = $user_id == 0 ? get_current_user_id() : $user_id;
    $paid_order_statuses = array_map( 'esc_sql', wc_get_is_paid_statuses() );

    $results = $wpdb->get_col( "
        SELECT p.ID FROM {$wpdb->prefix}posts AS p
        INNER JOIN {$wpdb->prefix}postmeta AS pm ON p.ID = pm.post_id
        WHERE p.post_status IN ( 'wc-" . implode( "','wc-", $paid_order_statuses ) . "' )
        AND p.post_type LIKE 'shop_order'
        AND pm.meta_key = '_customer_user'
        AND pm.meta_value = $customer_id
    " );

    // Count number of orders and return a boolean value depending if higher than 0
    return count( $results ) > 0 ? true : false;
}

代码放在活动子主题(或主题)的function.php文件中,或者放在任何插件文件中。

此代码在Woocommerce 3+上进行测试并且有效(它也适用于以前的版本)。

  

适用于多种产品: Check if a customer has purchased a specific products in WooCommerce

使用示例1 (登录客户)

if( has_bought() )
    echo '<p>You have already maid a purchase</p>';
else
    echo '<p>Welcome, for your first purchase you will get a discount of 10%</p>';

使用示例2 (设置$ user_id)

// Define the user ID
$user_id = 85;

if( has_bought( $user_id ) )
        echo '<p>customer have already maid a purchase</p>';
    else
        echo '<p>Customer with 0 purchases</p>';

如果未定义$user_id并且当前用户未登录,则此函数将返回false

  

此函数的代码部分基于内置的WooCommerce函数wc_customer_bought_product源代码。

答案 2 :(得分:1)

从@Antonio Novak的简化版本开始,我对覆盖所有可能的订单状态(表明用户已经购买)进行了一些改进。

状态列表

WooCommerce提供了有关状态的详细文档。签出:Playground Link

但是,我在这里使用子弹记录列表:

$order_statuses = array(
    'wc-pending'    => _x( 'Pending payment', 'Order status', 'woocommerce' ),
    'wc-processing' => _x( 'Processing', 'Order status', 'woocommerce' ),
    'wc-on-hold'    => _x( 'On hold', 'Order status', 'woocommerce' ),
    'wc-completed'  => _x( 'Completed', 'Order status', 'woocommerce' ),
    'wc-cancelled'  => _x( 'Cancelled', 'Order status', 'woocommerce' ),
    'wc-refunded'   => _x( 'Refunded', 'Order status', 'woocommerce' ),
    'wc-failed'     => _x( 'Failed', 'Order status', 'woocommerce' ),
);

此外,我决定添加wc装运状态。当然是自定义状态,但是通常由电子商务使用,对吗?

我不是问用户是否已经购买过,而是假设最大的兴趣可能是提供更多的诱因来赢得新用户,而是选择将问题和功能的答案倒置为自由。

使用建议的功能时,对于用户的首次购买,返回值将为true;而对于已经在查询中列出的状态的订单,则返回false。

此外,我还使user id参数成为可选参数,因此可以在多种情况下重用该功能,而不仅仅是在用户会话中。

功能

function is_the_first_purchase( $user_id = 0) {
  
  if( $user_id == 0 ){
    $user_id = get_current_user_id();
  }
  
  if( ! $user_id ){
    return true;
  }
  
  $customer_orders = get_posts( array(
    'numberposts' => -1,
    'post_type'   => 'shop_order',
    'post_status' => array(
      'wc-completed', 
      'wc-on-hold', 
      'wc-processing', 
      'wc-shipped', 
      'wc-refunded'
    ),
    'meta_query' => array(
      array(
        'key'         => '_customer_user',
        'meta_value'  => $user_id,
      )
    )
  ));
  
  // return "true" when customer 
  // does not have an completed order

  return count( $customer_orders ) > 0 ? false : true;
}

答案 3 :(得分:1)

带有缓存层的版本(使用临时API密钥,为期一周)。未登录的用户返回false。

function has_bought() {

  if(!is_user_logged_in()) return false;

  $transient = 'has_bought_'.get_current_user_id();
  $has_bought = get_transient($transient);

  if(!$has_bought) {

  // Get all customer orders
  $customer_orders = get_posts( array(
    'numberposts' => 1, // one order is enough
    'meta_key'    => '_customer_user',
    'meta_value'  => get_current_user_id(),
    'post_type'   => 'shop_order', // WC orders post type
    'post_status' => 'wc-completed', // Only orders with "completed" status
    'fields'      => 'ids', // Return Ids "completed"
  ) );

    $has_bought = count($customer_orders) > 0 ? true : false;

    set_transient($transient, $has_bought, WEEK_IN_SECONDS);

  }

  // return "true" when customer has already at least one order (false if not)
  return $has_bought;
}

答案 4 :(得分:0)

简化版:

function has_bought() {
    // Get all customer orders
    $customer_orders = get_posts( array(
        'numberposts' => -1,
        'meta_key'    => '_customer_user',
        'meta_value'  => get_current_user_id(),
        'post_type'   => 'shop_order', // WC orders post type
        'post_status' => 'wc-completed' // Only orders with status "completed"
    ) );
    // return "true" when customer has already one order
    return count( $customer_orders ) > 0 ? true : false;
}

答案 5 :(得分:0)

如果启用了访客检查,则此功能可能有帮助

只需发送 $ customer_email 作为参数,函数将检入该电子邮件的所有订单并返回true或false。

function has_bought($customer_email){

  $orders = get_posts(array(
  'numberposts' => -1,
  'post_type' => 'shop_order',
  'post_status' => array('wc-processing', 'wc-completed'),
  ));

$email_array = array();

foreach($orders as $order) {

$order_obj = wc_get_order($order->ID);
$order_obj_data = $order_obj->get_data();

array_push($email_array, $order_obj_data['billing']['email']);

}


if (in_array($customer_email, $email_array)) {
return true;
} else {
return false;
}

}

答案 6 :(得分:0)

具有付费状态或仅与状态无关的查询的增强版本,还改进了PHP 5.4+的位代码键入:

function has_bought(int $user_id = 0, bool $paid = true ) {

    global $wpdb;

    $user_id = (empty($user_id)) ? get_current_user_id() : $user_id;

    $sql_str = "
        SELECT p.ID FROM ".$wpdb->posts." AS p
        INNER JOIN 
            ".$wpdb->postmeta." AS pm ON p.ID = pm.post_id
        WHERE 
            p.post_type LIKE 'shop_order'
        AND pm.meta_key = '_customer_user'
        AND pm.meta_value = %d
    ";

    $args = [(int) $user_id];

    if ($paid === true) {
        $paid_order_statuses = array_map( 'esc_sql', wc_get_is_paid_statuses() );
        $sql_str .= "AND p.post_status IN ( 'wc-" . implode( "','wc-", $paid_order_statuses ) . "' )";
    }

    $sql = $wpdb->prepare($sql_str, $args);

    return (bool) $wpdb->get_var( $sql );
}

答案 7 :(得分:0)

对于在 WC 中编码的任何人来说,这都是一项非常常见的任务。也许一个用于管理它的类(并在将来使检查更容易)是一个好主意。特别是因为 WC_Customer 类有几个方法可用于为此目的返回布尔值。

https://wp-helpers.com/2021/03/19/woocommerce-a-much-better-way-of-checking-if-an-user-has-purchases/