WooCommerce自定义代码实现按地理位置显示租赁产品问题
WooCommerce 租赁产品地理位置可见性修正方案
原代码存在的问题
- 全局
$product误用:woocommerce_product_query是修改产品列表查询的钩子,此时尚未生成单个产品对象,直接调用$product->get_id()属于逻辑错误,还会引发未定义变量报错。 - 变量未定义:
$product_id未初始化就调用get_id(),属于语法错误。 - 自定义字段取值错误:
get_post_meta默认返回数组,导致后续与字符串类型的用户账单地址对比失效,需传入第三个参数true获取单个值。 - 查询参数使用错误:
post__not_in用于排除指定产品ID,而非分类slug,原代码传入array('rentals')完全无效。 - 逻辑颠倒:需求是显示匹配条件的产品,原代码却试图排除分类,逻辑完全错误。
修正后的代码
add_action( 'woocommerce_product_query', 'myshop_restrict_rental_products_by_location', 9999, 2 ); function myshop_restrict_rental_products_by_location( $q, $query ) { // 仅对前台主产品查询生效,不影响后台管理 if ( is_admin() || ! $query->is_main_query() ) { return; } $user = wp_get_current_user(); $rental_category_slug = 'rentals'; // 未登录用户:隐藏所有租赁类产品 if ( empty( $user->ID ) ) { $tax_query = $q->get( 'tax_query', array() ); $tax_query[] = array( 'taxonomy' => 'product_cat', 'field' => 'slug', 'terms' => $rental_category_slug, 'operator' => 'NOT IN', ); $q->set( 'tax_query', $tax_query ); return; } // 获取用户账单地址的州/城市 $customer_state = get_user_meta( $user->ID, 'billing_state', true ); // 用户未填写账单地址:隐藏租赁类产品 if ( empty( $customer_state ) ) { $tax_query = $q->get( 'tax_query', array() ); $tax_query[] = array( 'taxonomy' => 'product_cat', 'field' => 'slug', 'terms' => $rental_category_slug, 'operator' => 'NOT IN', ); $q->set( 'tax_query', $tax_query ); return; } // 筛选条件:属于租赁分类 + 产品位置匹配用户账单地址 $tax_query = $q->get( 'tax_query', array() ); $tax_query[] = array( 'taxonomy' => 'product_cat', 'field' => 'slug', 'terms' => $rental_category_slug, 'operator' => 'IN', ); $meta_query = $q->get( 'meta_query', array() ); $meta_query[] = array( 'key' => 'custom_product_location', 'value' => $customer_state, 'compare' => '=', ); $q->set( 'tax_query', $tax_query ); $q->set( 'meta_query', $meta_query ); }
代码说明
- 后台过滤:通过
is_admin()判断,避免修改后台产品列表的查询逻辑,只影响前台商店页面。 - 分层逻辑:
- 未登录用户直接隐藏所有租赁类产品;
- 登录但未填写账单地址的用户,同样隐藏租赁类产品;
- 登录且有账单地址的用户,仅显示属于租赁分类且
custom_product_location与用户billing_state匹配的产品。
- 高效查询:通过
tax_query和meta_query直接在数据库查询阶段筛选产品,比单个产品循环判断效率更高,也避免了页面加载后再隐藏产品的闪烁问题。
内容的提问来源于stack exchange,提问作者George Obonyo
相关产品推荐
相关产品推荐

