You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WordPress:wp_set_object_terms无法为产品分配自定义分类regions

解决Dokan产品与自定义分类(Region)关联失效问题

问题描述

我通过ACF创建了名为regions的自定义分类,同时在Dokan多商户后台添加了地区选择下拉框,代码如下:

<?php
$regions = get_terms([
    'hierarchical' => 1,
    'show_option_none' => '',
    'hide_empty' => 0,
    'taxonomy' => 'region'
]);
?>
    <label for="regions"><?php esc_html_e('Region', 'your-text-domain'); ?></label><br>
    <input type="hidden" name="region_id" id="region_id" value="">
    <select name="regions" class="dokan-form-control">
        <option value=""><?php esc_html_e('Select Region', 'your-text-domain'); ?></option>
        <?php foreach ($regions as $region) {
        $parent_categories = get_terms([
            'taxonomy' => 'region',
            'hide_empty' => false,
            'parent' => $region->term_id
        ]);
        if (!empty($parent_categories)) { // check if there are any child categories
            ?>
            <?php foreach ($parent_categories as $parent_category) {
                $child_categories = get_terms([
                'taxonomy' => 'region',
                'hide_empty' => false,
                'parent' => $parent_category->term_id
                ]);
                if (!empty($child_categories)) { // check if there are any child categories
                ?>
                <optgroup label="<?php echo $parent_category->name; ?>">
                    <?php foreach ($child_categories as $child_category) { ?>
                    <option value="<?php echo $child_category->term_taxonomy_id; ?>" id="in-region-<?php echo $child_category->term_taxonomy_id; ?>"> <?php echo $child_category->name; ?> </option>
                    <?php } ?>
                </optgroup>
                <?php } ?>
            <?php } ?>
        <?php } ?>
        <?php } ?>
    </select>

尝试在产品创建后关联选中地区,修改了dokan-lit/includes/Dashboard/Templates/Products.php中的handle_product_add方法,但操作未生效,核心关联代码如下:

$regionId       = sanitize_text_field($postdata['regions']);
// ...
wp_set_object_terms($product_id, $regionId, 'regions');

完整的handle_product_add方法代码:

public function handle_product_add() {
        if ( ! is_user_logged_in() ) {
            return;
        }

        if ( ! dokan_is_user_seller( get_current_user_id() ) ) {
            return;
        }

        if ( ! isset( $_POST['dokan_add_new_product_nonce'] ) || ! wp_verify_nonce( sanitize_key( $_POST['dokan_add_new_product_nonce'] ), 'dokan_add_new_product' ) ) {
            return;
        }

        $postdata = wp_unslash( $_POST ); // phpcs:ignore

        $errors             = [];
        self::$product_cat  = - 1;
        self::$post_content = __( 'Details of your product ...', 'dokan-lite' );

        if ( isset( $postdata['add_product'] ) ) {
            $post_title     = sanitize_text_field( $postdata['post_title'] );
            $post_content   = wp_kses_post( $postdata['post_content'] );
            $post_excerpt   = wp_kses_post( $postdata['post_excerpt'] );
            $featured_image = absint( sanitize_text_field( $postdata['feat_image_id'] ) );
            $regionId       = sanitize_text_field($postdata['regions']);

            if ( empty( $post_title ) ) {
                $errors[] = __( 'Please enter product title', 'dokan-lite' );
            }

            if ( ! isset( $postdata['chosen_product_cat'] ) ) {
                if ( Helper::product_category_selection_is_single() ) {
                    if ( absint( $postdata['product_cat'] ) < 0 ) {
                        $errors[] = __( 'Please select a category', 'dokan-lite' );
                    }
                } else {
                    if ( ! isset( $postdata['product_cat'] ) || empty( $postdata['product_cat'] ) ) {
                        $errors[] = __( 'Please select at least one category', 'dokan-lite' );
                    }
                }
            } elseif ( empty( $postdata['chosen_product_cat'] ) ) {
                $errors[] = __( 'Please select a category', 'dokan-lite' );
            }

            self::$errors = apply_filters( 'dokan_can_add_product', $errors );

            if ( ! self::$errors ) {
                $timenow        = dokan_current_datetime()->setTimezone( new \DateTimeZone( 'UTC' ) );
                $product_status = dokan_get_new_post_status();
                $post_data      = apply_filters(
                    'dokan_insert_product_post_data', [
                        'post_type'         => 'product',
                        'post_status'       => $product_status,
                        'post_title'        => $post_title,
                        'post_content'      => $post_content,
                        'post_excerpt'      => $post_excerpt,
                        'post_date_gmt'     => $timenow->format( 'Y-m-d H:i:s' ),
                        'post_modified_gmt' => $timenow->format( 'Y-m-d H:i:s' ),
                    ]
                );

                $product_id = wp_insert_post( $post_data );

                
                if ( $product_id ) {
                    
                    wp_set_object_terms($product_id, $regionId, 'regions');
                    // 设置图片
                    if ( $featured_image ) {
                        set_post_thumbnail( $product_id, $featured_image );
                    }

                    if ( isset( $postdata['product_tag'] ) && ! empty( $postdata['product_tag'] ) ) {
                        $tags_ids = array_map( 'absint', (array) $postdata['product_tag'] );
                        wp_set_object_terms( $product_id, $tags_ids, 'product_tag' );
                    }

                    /* 设置产品分类 */
                    if ( ! isset( $postdata['chosen_product_cat'] ) ) {
                        if ( Helper::product_category_selection_is_single() ) {
                            wp_set_object_terms( $product_id, (int) $postdata['product_cat'], 'product_cat' );
                        } else {
                            if ( isset( $postdata['product_cat'] ) && ! empty( $postdata['product_cat'] ) ) {
                                $cat_ids = array_map( 'absint', (array) $postdata['product_cat'] );
                                wp_set_object_terms( $product_id, $cat_ids, 'product_cat' );
                            }
                        }
                    } else {
                        $chosen_cat = Helper::product_category_selection_is_single() ? [ reset( $postdata['chosen_product_cat'] ) ] : $postdata['chosen_product_cat'];
                        Helper::set_object_terms_from_chosen_categories( $product_id, $chosen_cat );
                    }

                    /** 设置产品类型,默认是simple */
                    $product_type = empty( $postdata['product_type'] ) ? 'simple' : $postdata['product_type'];
                    wp_set_object_terms( $product_id, $product_type, 'product_type' );

                    // 相册图片
                    if ( ! empty( $postdata['product_image_gallery'] ) ) {
                        $attachment_ids = array_filter( explode( ',', wc_clean( $postdata['product_image_gallery'] ) ) );
                        update_post_meta( $product_id, '_product_image_gallery', implode( ',', $attachment_ids ) );
                    }

                    if ( isset( $postdata['_regular_price'] ) ) {
                        update_post_meta( $product_id, '_regular_price', ( $postdata['_regular_price'] === '' ) ? '' : wc_format_decimal( $postdata['_regular_price'] ) );
                    }

                    if ( isset( $postdata['_sale_price'] ) ) {
                        update_post_meta( $product_id, '_sale_price', ( $postdata['_sale_price'] === '' ? '' : wc_format_decimal( $postdata['_sale_price'] ) ) );
                        $date_from = isset( $postdata['_sale_price_dates_from'] ) ? wc_clean( $postdata['_sale_price_dates_from'] ) : '';
                        $date_to   = isset( $postdata['_sale_price_dates_to'] ) ? wc_clean( $postdata['_sale_price_dates_to'] ) : '';
                        $now       = dokan_current_datetime();

                        // 日期设置
                        if ( $date_from ) {
                            update_post_meta( $product_id, '_sale_price_dates_from', $now->modify( $date_from )->setTime( 0, 0, 0 )->getTimestamp() );
                        } else {
                            update_post_meta( $product_id, '_sale_price_dates_from', '' );
                        }

                        if ( $date_to ) {
                            update_post_meta( $product_id, '_sale_price_dates_to', $now->modify( $date_to )->setTime( 23, 59, 59 )->getTimestamp() );
                        } else {
                            update_post_meta( $product_id, '_sale_price_dates_to', '' );
                        }

                        if ( $date_to && ! $date_from ) {
                            update_post_meta( $product_id, '_sale_price_dates_from', $now->setTime( 0, 0, 0 )->getTimestamp() );
                        }

                        if ( '' !== $postdata['_sale_price'] && '' === $date_to && '' === $date_from ) {
                            update_post_meta( $product_id, '_price', wc_format_decimal( $postdata['_sale_price'] ) );
                        } else {
                            update_post_meta( $product_id, '_price', ( $postdata['_regular_price'] === '' ) ? '' : wc_format_decimal( $postdata['_regular_price'] ) );
                        }
                        // 如果处于促销期则更新价格
                        if ( '' !== $postdata['_sale_price'] && $date_from && $now->modify( $date_from )->getTimestamp() < $now->getTimestamp() ) {
                            update_post_meta( $product_id, '_price', wc_format_decimal( $postdata['_sale_price'] ) );
                        }
                    }

                    update_post_meta( $product_id, '_visibility', 'visible' );
                    update_post_meta( $product_id, '_stock_status', 'instock' );

                    do_action( 'dokan_new_product_added', $product_id, $postdata );

                    if ( current_user_can( 'dokan_edit_product' ) ) {
                        $redirect = dokan_edit_product_url( $product_id );
                    } else {
                        $redirect = dokan_get_navigation_url( 'products' );
                    }

                    if ( 'create_and_add_new' === $postdata['add_product'] ) {
                        $redirect = add_query_arg(
                            [
                                'created_product'          => $product_id,
                                '_dokan_add_product_nonce' => wp_create_nonce( 'dokan_add_product_nonce' ),
                            ],
                            dokan_get_navigation_url( 'new-product' )
                        );
                    }

                    wp_safe_redirect( apply_filters( 'dokan_add_new_product_redirect', $redirect, $product_id ) );
                    exit;

                }
            }
        }
    }

问题分析与修复步骤

1. 分类法名称不匹配

前端获取分类时用的是taxonomy' => 'region',但后端关联时写的是'regions',两者不一致导致关联失败。

修复代码:
将handle_product_add中的关联代码:

wp_set_object_terms($product_id, $regionId, 'regions');

改为:

wp_set_object_terms($product_id, $regionId, 'region');

2. 传递错误的ID类型

前端下拉框选项值用的是$child_category->term_taxonomy_id,但wp_set_object_terms需要的是term_id或分类slug,而非term_taxonomy_id。

修复前端代码:
将选项中的term_taxonomy_id替换为term_id:

<option value="<?php echo $child_category->term_id; ?>" id="in-region-<?php echo $child_category->term_id; ?>"> <?php echo $child_category->name; ?> </option>

3. 未验证地区ID有效性

需要确保$regionId不为空且是有效的分类ID,避免无效值传入导致关联失败。

修复后端代码:
在关联前添加验证逻辑:

if (!empty($regionId) && term_exists((int)$regionId, 'region')) {
    wp_set_object_terms($product_id, (int)$regionId, 'region');
}

4. 避免修改Dokan核心文件(推荐)

直接修改Dokan核心文件会导致插件更新时代码丢失,建议使用Dokan提供的dokan_new_product_added动作钩子来处理关联逻辑,将代码放在主题的functions.php或自定义插件中:

add_action('dokan_new_product_added', 'dokan_assign_product_region', 10, 2);
function dokan_assign_product_region($product_id, $postdata) {
    if (!isset($postdata['regions']) || empty($postdata['regions'])) {
        return;
    }

    $regionId = absint($postdata['regions']);
    if (term_exists($regionId, 'region')) {
        wp_set_object_terms($product_id, $regionId, 'region');
    }
}

使用钩子后,可删除之前在handle_product_add中添加的关联代码。

内容的提问来源于stack exchange,提问作者Maison012

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 12:22:03