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
相关产品推荐
相关产品推荐

