Проверьте, приобрел ли клиент определенные товары в WooCommerce
Мне нужно проверить, приобрел ли клиент определенный продукт ранее в WooCommerce.
Дело обстоит так: Клиент не сможет приобрести продукт "c", "d", "e", если он не приобрел продукт "a" или "b" в более раннее время.
Если клиент приобрел продукт "a" или "b" ранее, то активируется кнопка покупки продукта "c", "d" и "e", и им разрешается их покупать.
Если они не приобрели "a" или "b" ранее, они будут не разрешается приобретать "c", "d", "e", и кнопка покупки деактивирована.
Как я могу этого добиться?
Спасибо.
4 answers
Обновлено ( совместимость для Woocommerce 3+)
Да, это возможно, написав условную функцию, которая возвращает "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 которые вы ранее скопировали в свою активную дочернюю тему или тему:
- Шаблон для страницы магазина , касающейся
add-to-cart
кнопка - этоloop/add-to-cart.php
. - Шаблоны для Страниц продуктов , касающиеся
add-to-cart
кнопка находится вsingle-product/add-to-cart
папка в зависимости от типов ваших продуктов.
Вот пример, который вы могли бы использовать в этих шаблоны (выше):
// 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
класс.
В этом случае также можно использовать встроенную функцию woocommerce wc_customer_bought_product
.
Смотрите использование функции здесь.
Я бы сделал это таким образом;
Это не будет вносить никаких изменений в шаблон woocommerce, а только использовать фильтр woocommerce_is_purchasable
Это все функции,
-
Проверьте, если текущий идентификатор продукта уже принесен клиентом, в версии 2.6+ woocommerce реализовала функцию
wc_customer_bought_product
, чтобы проверить, принес ли клиент уже продукт, я никогда не использовал его раньше, но на основе документов вы можете создать функцию, как показано ниже, для проверки массива продуктов Идентификатор, если один из них уже был доставлен;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; } } }
Предыдущий метод, который я использую, чтобы проверить, был ли конкретный идентификатор продукта уже доставлен клиентом, приведен ниже, поэтому вы можете использовать любую из этих функций, хотя та, которую я создал, не предназначена для массива идентификаторов
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;
}
- Теперь, когда мы можем проверить, внесен ли уже идентификатор продукта или нет, мы можем просто добавить фильтр на
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
или в любом месте, где вы хотите, чтобы оно отображалось.
Новая версия компактная, легкая, быстрая и совместимая со всеми версиями woocommerce (2.4+)
Ниже приведена новая версия моей условной функции, частично основанная на встроенной функции woocommerce wc_customer_bought_product
исходный код:
Существует 2 необязательных аргумента $user_id
и $product_ids
:
-
$user_id
позволит вам указать определенный идентификатор пользователя (когда не используется для текущего входа в систему пользователь); -
$product_ids
( массив) позволит указать определенные идентификаторы продуктов для проверки
Вот этот код:
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(woim.meta_value) 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 файл вашей активной дочерней темы (или темы) или также в любом файле плагина.
Этот код протестирован на Woocommerce 3+ и работает (он должен работать и в предыдущих версиях).
ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ:
Пример 1 ( вошедший в систему клиент): Обнаружение, если текущий пользователь купил один из определенных продуктов (идентификаторы продуктов должны быть массивом)
// 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
) Определение того, купил ли определенный пользователь один из определенных продуктов (идентификаторы продуктов должны быть массивом)
// 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
.