web-dev-qa-db-ja.com

顧客がWooCommerceで特定の製品を購入したかどうかを確認します

顧客が以前にWooCommerceで特定の製品を購入したかどうかを確認する必要があります。

この場合、お客様は、以前に製品「a」または「b」を購入していない限り、製品「c」、「d」、「e」を購入することはできません。

顧客が以前に製品「a」または「b」を購入した場合、製品「c」、「d」、および「e」の購入ボタンがアクティブになり、購入が許可されます。

以前に「a」または「b」を購入したことがない場合、「c」、「d」、「e」を購入することはできず、購入ボタンは無効になります。

どうすればこれを達成できますか?

ありがとう。

6
alegjos

更新(Woocommerce 3+との互換性)

はい、可能です。現在の顧客が特定の定義済み製品IDをすでに購入している場合に、「true」を返す条件関数を記述します。 このコードは、アクティブな子テーマまたはテーマのfunction.phpファイルにあります。

条件関数は次のとおりです。

function has_bought_items() {
    $bought = false;

    // Set HERE ine the array your specific target product IDs
    $prod_arr = array( '21', '67' );

    // 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"
    ) );
    foreach ( $customer_orders as $customer_order ) {
        // Updated compatibility with WooCommerce 3+
        $order_id = method_exists( $order, 'get_id' ) ? $order->get_id() : $order->id;
        $order = wc_get_order( $customer_order );

        // Iterating through each current customer products bought in the order
        foreach ($order->get_items() as $item) {
            // WC 3+ compatibility
            if ( version_compare( WC_VERSION, '3.0', '<' ) ) 
                $product_id = $item['product_id'];
            else
                $product_id = $item->get_product_id();

            // Your condition related to your 2 specific products Ids
            if ( in_array( $product_id, $prod_arr ) ) 
                $bought = true;
        }
    }
    // return "true" if one the specifics products have been bought before by customer
    return $bought;
}

このコードはテストされて機能します。


使用法:
たとえば、以前にアクティブな子テーマまたはテーマにコピーしたいくつかのWooCommerceテンプレートで使用できます。

これらのテンプレートで使用できる例を次に示します(上記)

// Replace the numbers by your special restricted products IDs
$restricted_products = array( '20', '32', '75' );

// compatibility with WC +3
$product_id = method_exists( $product, 'get_id' ) ? $product->get_id() : $product->id;

// customer has NOT already bought a specific product for this restricted products
if ( !has_bought_items() && in_array( $product_id, $restricted_products ) ) { 

    // Displaying an INACTIVE add-to-cart button (With a custom text, style and without the link).
    // (AND optionally) an explicit message for example.

// ALL OTHER PRODUCTS OR RESTRICTED PRODUCTS IF COSTUMER HAS ALREADY BOUGHT SPECIAL PRODUCTS
} else { 

    // place for normal Add-To-Cart button code here
}

そしてここ完全な適用例からadd-to-cartボタンテンプレートショップページ

<?php
/**
 * Loop Add to Cart
 *
 * This template can be overridden by copying it to yourtheme/woocommerce/loop/add-to-cart.php.
 *
 * HOWEVER, on occasion WooCommerce will need to update template files and you
 * (the theme developer) will need to copy the new files to your theme to
 * maintain compatibility. We try to do this as little as possible, but it does
 * happen. When this occurs the version of the template file will be bumped and
 * the readme will list any important changes.
 *
 * @see         https://docs.woocommerce.com/document/template-structure/
 * @author      WooThemes
 * @package     WooCommerce/Templates
 * @version     2.5.0
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

global $product;

// Replace the numbers by your special restricted products IDs
$restricted_products = array( '37', '53', '70' );

// compatibility with WC +3
$product_id = method_exists( $product, 'get_id' ) ? $product->get_id() : $product->id;

if ( !has_bought_items() && in_array( $product_id, $restricted_products ) ) {

    echo '<a class="button greyed_button">' . __("Disabled", "your_theme_slug") . '</a>';
    echo '<br><span class="greyed_button-message">' . __("Your message goes here…", "your_theme_slug") . '</span>';

} else {

echo apply_filters( 'woocommerce_loop_add_to_cart_link',
    sprintf( '<a rel="nofollow" href="%s" data-quantity="%s" data-product_id="%s" data-product_sku="%s" class="%s">%s</a>',
        esc_url( $product->add_to_cart_url() ),
        esc_attr( isset( $quantity ) ? $quantity : 1 ),
        esc_attr( $product_id ),
        esc_attr( $product->get_sku() ),
        esc_attr( isset( $class ) ? $class : 'button' ),
        esc_html( $product->add_to_cart_text() )
    ),
$product );

}

アクティブな子テーマまたはテーマのgreyed_buttonファイルのstyle.cssクラスで非アクティブボタンのスタイルを設定します。 greyed_button-messageクラスのメッセージについても同じです。

8
LoicTheAztec

新しいバージョンコンパクト、軽量、高速で、すべてのバージョンのwoocommerceと互換性があります(バージョン2.4以降)

これは、組み込みのwoocommerce関数 wc_customer_bought_product ソースコードに部分的に基づいた、新しく拡張された軽量の条件関数です。

2つのオプションの引数$user_id$product_idsがあります。

  • $user_idを使用すると、定義済みのユーザーIDを指定できます(現在ログインしているユーザーに使用されていない場合);
  • $product_ids(array)は、チェックする定義済みの製品IDを指定できるようにします

そのコードは次のとおりです。

function has_bought_items( $user_id = 0,  $product_ids = 0 ) {
    global $wpdb;
    $customer_id = $user_id == 0 || $user_id == '' ? get_current_user_id() : $user_id;
    $statuses      = array_map( 'esc_sql', wc_get_is_paid_statuses() );

    if ( is_array( $product_ids ) )
        $product_ids = implode(',', $product_ids);

    if ( $product_ids !=  ( 0 || '' ) )
        $query_line = "AND woim.meta_value IN ($product_ids)";
    else
        $query_line = "AND woim.meta_value != 0";

    // Count the number of products
    $product_count_query = $wpdb->get_var( "
        SELECT COUNT(p.ID) FROM {$wpdb->prefix}posts AS p
        INNER JOIN {$wpdb->prefix}postmeta AS pm ON p.ID = pm.post_id
        INNER JOIN {$wpdb->prefix}woocommerce_order_items AS woi ON p.ID = woi.order_id
        INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS woim ON woi.order_item_id = woim.order_item_id
        WHERE p.post_status IN ( 'wc-" . implode( "','wc-", $statuses ) . "' )
        AND pm.meta_key = '_customer_user'
        AND pm.meta_value = $customer_id
        AND woim.meta_key IN ( '_product_id', '_variation_id' )
        $query_line
    " );

    // Return a boolean value if count is higher than 0
    return $product_count_query > 0 ? true : false;
}

コードは、アクティブな子テーマ(またはテーマ)のfunction.phpファイル、または任意のプラグインファイルに挿入されます。

このコードはWoocommerce3 +でテストされ、機能します(以前のバージョンでも機能するはずです)。


使用例:

例1(ログインした顧客):現在のユーザーが定義された製品の1つを購入したかどうかを検出する(製品IDは配列である必要があります)

// Define the targeted Products IDs
$product_ids = array( 38, 41, 85, 95 );

if( has_bought_items( '', $product_ids ) )
    echo "<p>You have already purchased one of this products</p>";
else
    echo "<p>You have not yet purchased one of this products</p>";

例2$user_idの設定)定義されたユーザーが次のいずれかを購入したかどうかの検出定義された製品(製品IDは配列である必要があります)

// Define the user ID
$user_id = 85;

// Define the targeted Products IDs
$product_ids = array( 38, 41, 85, 95 );

if( has_bought_items( $user_id, $product_ids ) )
    echo "<p>This user have already purchased one of this products</p>";
else
    echo "<p>This user have not yet purchased one of this products</p>";

$user_idが定義されておらず、現在のユーザーがログインしていない場合、この関数はfalseを返します。

例3(ログインした顧客):現在のユーザーがすでに購入したかどうかを検出する

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

例4$user_idの設定)定義されたユーザーがすでに作成したかどうかの検出購入

// Define the user ID
$user_id = 85;

if( has_bought_items( $user_id ) )
        echo '<p>customer have already made a purchase</p>';
    else
        echo '<p>Customer with 0 purshases</p>';

ここで、$user_idが定義されていない場合および現在のユーザーログインしていない場合、この関数はfalseを返します。

5
LoicTheAztec

この場合、組み込みのwoocommerce関数wc_customer_bought_productも使用できます。

関数の使用法を参照してください ここ

4
Tim

私はそれをこのようにしているでしょう。

これはwoocommerceテンプレートの変更を行いませんが、フィルターwoocommerce_is_purchasableのみを使用します

これらはすべて機能です、

  1. 現在の製品IDがすでに顧客によって提供されているかどうかを確認します。バージョン2.6以降では、woocommerceは関数wc_customer_bought_productを実装して、顧客がすでに製品を提供しているかどうかを確認します。これまで使用したことはありませんが、作成できるドキュメントに基づいています製品IDの配列のいずれかがすでに持ち込まれている場合は、それらをチェックする以下のような関数。

    function cmk_check_product_brought( $ids=array() ) {
        if ( ! $ids ) return false;
        foreach ( $ids as $product => $id ) {
            if ( wc_customer_bought_product( wp_get_current_user()->user_email, get_current_user_id(), $id ) ) {
                return true;
            }
        }
    }
    

特定の製品IDがすでに顧客から提供されているかどうかを確認するために私が行った以前の方法は以下のとおりです。したがって、これらの関数のいずれかを使用できますが、作成した方法はIDの配列用ではありません。

function cmk_product_ordered( $id ) {
    // Get All order of current user
    $orders = get_posts( array(
        'numberposts' => -1,
        'meta_key'    => '_customer_user',
        'meta_value'  => get_current_user_id(),
        'post_type'   => wc_get_order_types( 'view-orders' ),
        'post_status' => array_keys( wc_get_order_statuses() )
    ) );

    if ( !$orders ) return false; // return if no order found

    $all_ordered_product = array(); // store all products ordered by ID in an array

    foreach ( $orders as $order => $data ) { // Loop through each order
        $order_data = new WC_Order( $data->ID ); // create new object for each order
        foreach ( $order_data->get_items() as $key => $item ) {  // loop through each order item
            // store in array with product ID as key and order date a value
            $all_ordered_product[ $item['product_id'] ] = $data->post_date; 
        }
    }
    // check if defined ID is found in array
    if ( isset( $all_ordered_product[ $id ] ) ) return true;
    else return false;
}
  1. 商品IDが既に取得されているかどうかを確認できるようになったので、woocommerce_is_purchasableにフィルターを追加して独自の条件を作成できます。以下のこの関数は、達成しようとしていることの簡単な例です。

$required_purchased$conditional_purchaseの値を変更しました。

function cmk_disable_product_purchase( $purchasable, $product ) {

    // array of products required to be purchase first
    $required_purchased = array( 1, 2);

    // array of restricted/conditional products to be purchase
    $conditional_purchase = array( 3,4,5);

    // Get the ID for the current product
    $product_id = $product->is_type( 'variation' ) ? $product->variation_id : $product->id;

    //return default $purchasable if current product ID is not in restricted array
    if ( !in_array($product_id, $conditional_purchase)) return $purchasable;

    /**
     ** Check if one required products has been purchase;
     **/

    // using cmk_check_product_brought() function, return false if product is not purchase
    if ( ! cmk_check_product_brought( $required_purchased ) ) $purchasable = false;

    // using cmk_product_ordered() function, you can use this instead
    /*if ( cmk_product_ordered( 1 )  || cmk_product_ordered( 2 ) ) {
        $purchasable = $purchasable; //return default if one product is purchased
    } else {
        $purchasable = false;
    }*/

    // Double-check for variations: if parent is not purchasable, then variation is not
    if ( $purchasable && $product->is_type( 'variation' ) ) {
        $purchasable = $product->parent->is_purchasable();
    }

    return $purchasable;
}
add_filter( 'woocommerce_variation_is_purchasable', 'cmk_disable_product_purchase', 10, 2 );
add_filter( 'woocommerce_is_purchasable', 'cmk_disable_product_purchase', 10, 2 );

そして、それは製品を購入不可として設定するはずです(カートに追加ボタンは自動的に非表示になります)。これで、購入できない商品のメッセージを追加する場合は、cmk_disable_product_purchaseと同じ条件を使用してメッセージを追加し、woocommerce_single_product_summaryまたは表示したい場所にフックするだけです。

2
silver