Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/255.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/wordpress/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 检查客户是否已经在WooCommerce中购买了东西_Php_Wordpress_Woocommerce_Product_Orders - Fatal编程技术网

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

Php 检查客户是否已经在WooCommerce中购买了东西,php,wordpress,woocommerce,product,orders,Php,Wordpress,Woocommerce,Product,Orders,我想创建一个WooCommerce插件,为有购买历史的客户添加一些优惠 如何检查用户以前购买的东西 谢谢 更新2020: 是可以创建一个条件函数,当客户至少有一个状态为已完成的订单时,该函数返回true 以下是此条件函数的代码: function has_bought() { // Get all customer orders $customer_orders = get_posts( array( 'numberposts' => 1, // one

我想创建一个WooCommerce插件,为有购买历史的客户添加一些优惠

如何检查用户以前购买的东西

谢谢

更新2020


是可以创建一个条件函数,当客户至少有一个状态为已完成的订单时,该函数返回
true

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

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

    // return "true" when customer has already at least one order (false if not)
   return count($customer_orders) > 0 ? true : false; 
}
此代码经过测试并正常工作。

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


用法(作为条件):

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

参考资料

简化版:

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;
}
2021更新-处理客人“计费电子邮件”-改进和安全的SQL查询

这里有一个更轻更快的条件函数,如果客户已经购买了,该函数将返回true

它通过其用户ID处理注册用户guest,并通过其计费电子邮件处理guest:

  • 对于注册用户:如果可选参数未设置用户ID,则将使用当前用户ID
  • 对于来宾:计费电子邮件将作为函数中的参数
此较轻且经过改进的函数(部分基于函数源代码)将根据订单数返回布尔值(O订单为false,至少有一个已付款订单时为true):

代码位于活动子主题(或主题)的functions.php文件或任何插件文件中

这段代码在Woocommerce 3+上进行了测试,可以正常工作(在以前的版本上也可以正常工作)

对于多个产品:


使用示例1(已登录客户)

此函数的代码部分基于内置的WooCommerce函数
wc\u customer\u bulled\u product()
源代码


如果启用了来宾检查,则此功能可能会有所帮助

只需发送$customer\u 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;
}

}

对于PHP5.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 );
}

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

状态列表

WooCommerce提供关于状态的Detialed文档。请查看:

但是,在这里,我用slug记录了这个列表:

$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发货状态。当然,这是一种自定义状态,但通常由电子商务使用,对吗

我没有问用户是否已经购买,而是假设最大的兴趣可能是提供更多的激励来赢得新用户,我冒昧地将问题和函数的答案颠倒过来

当使用建议的功能时,当用户第一次购买时,退货将为真;当用户已经拥有查询中列出的状态的订单时,退货将为假

此外,我还将userid参数设置为可选的,因此该函数可以在多种情况下重用,而不仅仅是在用户会话中

功能

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;
}
具有缓存层的版本(使用瞬态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;
}

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


有没有办法同时显示/返回最近一次购买的日期?@RodrigoM return true如果客户一次性成功购买,该功能会帮助很大。目前我需要检查客户是否已经购买。如果他没有,我想申请折扣,我该如何改变购买的当前价值?(此功能将在确认购买/购物车时调用)为什么我们要查询所有订单,我们不需要
'numberposts'=>1,
?@LoicTheAztec如何在结帐页面使用此功能?如何将其转换为短码的想法,所以我可以用它包装内容?是的,它可以很容易地在短代码中完成…您需要什么规格?(如果你喜欢/想要,你可以投票选出这个有用的答案)…尽管你发送的链接包含有效和相关的信息,但考虑到链接将来可能会被删除,它们并不总是回答问题的最佳方式。有趣的是,您描述了建议的解决方案,并在可能的情况下添加了相关代码。
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 );
}
$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' ),
);
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;
}
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;
}