Смена роли пользователя Woocommerce после покупки определённого товара, как сделать?

Ссылка скопирована
1 ответ

Здравствуйте, сделать смену роли после покупки определённого товара я смог при помощи вот этого кода:

add_action( 'woocommerce_order_status_completed', 'tb_change_role_on_purchase_vip' );  function tb_change_role_on_purchase_vip( $order_id ) {  // get order object and items 	$order = new WC_Order( $order_id ); 	$items = $order->get_items();  	$product_id = 52; // Product ID  	foreach ( $items as $item ) {  		if( $product_id == $item['product_id'] && $order->user_id ) { 			$user = new WP_User( $order->user_id );  			// Remove old role             $user->remove_role( 'customer' );               // Add new role             $user->add_role( 'pro_mem' ); 		} 	} }

add_action( 'woocommerce_order_status_completed', 'tb_change_role_on_purchase_vip' ); function tb_change_role_on_purchase_vip( $order_id ) { // get order object and items $order = new WC_Order( $order_id ); $items = $order->get_items(); $product_id = 52; // Product ID foreach ( $items as $item ) { if( $product_id == $item['product_id'] && $order->user_id ) { $user = new WP_User( $order->user_id ); // Remove old role $user->remove_role( 'customer' ); // Add new role $user->add_role( 'pro_mem' ); } } }

и для второго товара

add_action( 'woocommerce_order_status_completed', 'tb_change_role_on_purchase_pro' );  function tb_change_role_on_purchase_pro( $order_id ) {  // get order object and items 	$order = new WC_Order( $order_id ); 	$items = $order->get_items();  	$product_id = 53; // Product ID  	foreach ( $items as $item ) {  		if( $product_id == $item['product_id'] && $order->user_id ) { 			$user = new WP_User( $order->user_id );  			// Remove old role             $user->remove_role( 'customer' );               // Add new role             $user->add_role( 'vip_mem' ); 		} 	} }

add_action( 'woocommerce_order_status_completed', 'tb_change_role_on_purchase_pro' ); function tb_change_role_on_purchase_pro( $order_id ) { // get order object and items $order = new WC_Order( $order_id ); $items = $order->get_items(); $product_id = 53; // Product ID foreach ( $items as $item ) { if( $product_id == $item['product_id'] && $order->user_id ) { $user = new WP_User( $order->user_id ); // Remove old role $user->remove_role( 'customer' ); // Add new role $user->add_role( 'vip_mem' ); } } }

Теперь собственно мой вопрос:
Как сделать чтобы после покупки первого товара (id товара 52) когда уже роль стала:
pro_mem
Покупая второй товар (id товара 53) роль pro_mem менялась на следующую роль vip_mem ?

Прописать такой вариант кода, например:

add_action( 'woocommerce_order_status_completed', 'tb_change_role_on_purchase_vip' );  function tb_change_role_on_purchase_vip( $order_id ) {  // get order object and items 	$order = new WC_Order( $order_id ); 	$items = $order->get_items();  	$product_id = 53; // Product ID  	foreach ( $items as $item ) {  		if( $product_id == $item['product_id'] && $order->user_id ) { 			$user = new WP_User( $order->user_id );  			// Remove old role             $user->remove_role( 'pro_mem' );               // Add new role             $user->add_role( 'vip_mem' ); 		} 	} }

add_action( 'woocommerce_order_status_completed', 'tb_change_role_on_purchase_vip' ); function tb_change_role_on_purchase_vip( $order_id ) { // get order object and items $order = new WC_Order( $order_id ); $items = $order->get_items(); $product_id = 53; // Product ID foreach ( $items as $item ) { if( $product_id == $item['product_id'] && $order->user_id ) { $user = new WP_User( $order->user_id ); // Remove old role $user->remove_role( 'pro_mem' ); // Add new role $user->add_role( 'vip_mem' ); } } }

Я правильно сделал?

Или же просто добавить во второй код удаление ещё одной роли:

// Remove old role             $user->remove_role( 'pro_mem' );

// Remove old role $user->remove_role( 'pro_mem' );

и тогда получится вот так:

add_action( 'woocommerce_order_status_completed', 'tb_change_role_on_purchase_vip' );  function tb_change_role_on_purchase_vip( $order_id ) {  // get order object and items 	$order = new WC_Order( $order_id ); 	$items = $order->get_items();  	$product_id = 53; // Product ID  	foreach ( $items as $item ) {  		if( $product_id == $item['product_id'] && $order->user_id ) { 			$user = new WP_User( $order->user_id );                            // Remove old role             $user->remove_role( 'customer' );   			// Remove old role             $user->remove_role( 'pro_mem' );               // Add new role             $user->add_role( 'vip_mem' ); 		} 	} }

add_action( 'woocommerce_order_status_completed', 'tb_change_role_on_purchase_vip' ); function tb_change_role_on_purchase_vip( $order_id ) { // get order object and items $order = new WC_Order( $order_id ); $items = $order->get_items(); $product_id = 53; // Product ID foreach ( $items as $item ) { if( $product_id == $item['product_id'] && $order->user_id ) { $user = new WP_User( $order->user_id ); // Remove old role $user->remove_role( 'customer' ); // Remove old role $user->remove_role( 'pro_mem' ); // Add new role $user->add_role( 'vip_mem' ); } } }

То есть если пользователь только зашёл на сайт и покупает первый товар (id товара 52), то присваивается роль pro_mem а если потом покупает второй товар (id товара 53) роль pro_mem будет удаляться и меняться на vip_mem
Вроде всё правильно сделал. Надо будет проверить )

Дополнительно:

Нужно решить такую задачу?

Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

Заказать помощь
Лучший ответ
1
Ольга Сеть Ответ

Делать отдельную функцию и отдельный hook для каждого товара не нужно. Лучше хранить соответствие “ID товара → роль” в массиве и обрабатывать заказ один раз. Так код будет проще поддерживать, и не будет конфликтов, если в заказе несколько подходящих товаров.

Пример:

add_action('woocommerce_order_status_completed', 'change_user_role_by_product');
 
function change_user_role_by_product($order_id) {
    $order = wc_get_order($order_id);
 
    if (!$order || !$order->get_user_id()) {
        return;
    }
 
    $role_map = [
        52 => 'pro_mem',
        53 => 'vip_mem',
    ];
 
    $user = new WP_User($order->get_user_id());
 
    foreach ($order->get_items() as $item) {
        $product_id = $item->get_product_id();
        $variation_id = $item->get_variation_id();
 
        foreach ([$product_id, $variation_id] as $id) {
            if (isset($role_map[$id])) {
                $user->set_role($role_map[$id]);
                return;
            }
        }
    }
}

add_action('woocommerce_order_status_completed', 'change_user_role_by_product'); function change_user_role_by_product($order_id) { $order = wc_get_order($order_id); if (!$order || !$order->get_user_id()) { return; } $role_map = [ 52 => 'pro_mem', 53 => 'vip_mem', ]; $user = new WP_User($order->get_user_id()); foreach ($order->get_items() as $item) { $product_id = $item->get_product_id(); $variation_id = $item->get_variation_id(); foreach ([$product_id, $variation_id] as $id) { if (isset($role_map[$id])) { $user->set_role($role_map[$id]); return; } } } }

set_role() заменит текущую роль пользователя на новую. Если нужно не заменить, а добавить роль, используйте add_role(). Но у пользователя с несколькими ролями могут быть неожиданные права, поэтому для membership-сценария чаще безопаснее именно set_role().

Если товар вариативный, проверяйте не только product_id, но и variation_id, как в примере. Иначе роль может не смениться при покупке конкретной вариации.

Также подумайте о возвратах и отменах. Если пользователь купил доступ, а заказ потом отменили или вернули, нужно решить, возвращать ли старую роль. Для этого можно добавить обработчики на cancelled, refunded или хранить старую роль в user meta.

Код лучше размещать не в теме, а в маленьком mu-plugin или кастомном плагине, потому что смена роли после покупки — бизнес-логика, она не должна пропадать при смене темы.

Другие ответы (0)

Пока нет других ответов. Будьте первым, кто поможет автору.

Ответить на вопрос

комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Вам также может быть интересно