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

如何通过Woocommerce钩子依据元数据筛选订单内可下载文件?

基于用户选择筛选WooCommerce可下载产品的附件

问题背景

我用WooCommerce搭建电商网站,部分产品是带有多个附件的可下载产品。需要根据用户加购时选择的选项,通过文件名与选项数组的字符串匹配,筛选用户能获取的下载文件。比如产品有“Weight 1、Weight 2、Weight 3”的下载文件,用户选了“Weight 1”和“Weight 3”,就只让他们获取这两个文件。

目前已经通过functions.php里的代码,把用户选择的选项成功存为订单项元数据数组:

// 保存选中的权重到购物车元数据
add_filter( 'woocommerce_add_cart_item_data', 'save_font_weights', 10, 3 );
function save_font_weights( $cart_item_data, $product_id, $variation_id ) {
  $fw = $_POST['font_weights'];

  if( !empty($fw) ) {
    $cart_item_data[ 'selected_font_weights' ] = $fw;

    // 确保每次加购都是独立订单项
    $cart_item_data['unique_key'] = md5( microtime().rand() );
    WC()->session->set( 'session_fw', $fw );
  }
  return $cart_item_data;
}

// 在购物车和结账页面显示自定义选项
add_filter( 'woocommerce_get_item_data', 'output_font_weights', 10, 2 );
function output_font_weights( $cart_data, $cart_item ) {
  if( isset( $cart_item['selected_font_weights'] ) ) {
    $cart_data[] = array(
      'key'       => __('Selected weights', 'woocommerce'),
      'value'     => $cart_item['selected_font_weights'],
      'display'   => $cart_item['selected_font_weights'],
    );
  }
  return $cart_data;
}

// 将购物车自定义元数据保存为订单项元数据,在订单和邮件中显示
add_action( 'woocommerce_checkout_create_order_line_item', 'save_weights_to_order', 10, 4 );
function save_weights_to_order( $item, $cart_item_key, $values, $order ) {
  if( isset($values['selected_font_weights']) && ! empty($values['selected_font_weights']) ) {
    // 去除原代码冗余操作,避免重复添加元数据
    $item->update_meta_data( __('Selected weights', 'woocommerce'), $values['selected_font_weights']);
  }
}

解决方案:使用woocommerce_order_item_get_downloads钩子筛选下载文件

WooCommerce提供了woocommerce_order_item_get_downloads过滤器,专门用来修改订单项的可下载文件列表。你可以通过这个钩子,结合已保存的订单项元数据,匹配文件名来筛选下载文件:

// 根据用户选择的选项筛选可下载文件
add_filter( 'woocommerce_order_item_get_downloads', 'filter_downloads_by_selected_weights', 10, 2 );
function filter_downloads_by_selected_weights( $downloads, $item ) {
    // 获取订单项中保存的选中权重
    $selected_weights = $item->get_meta( 'Selected weights' );
    
    // 如果没有选中的权重,直接返回原下载列表
    if ( empty( $selected_weights ) ) {
        return $downloads;
    }

    // 将选中的权重转为数组(如果存储的是逗号分隔字符串)
    if ( is_string( $selected_weights ) ) {
        $selected_weights = array_map( 'trim', explode( ',', $selected_weights ) );
    }

    // 筛选下载文件:文件名包含选中权重中的任意一个
    $filtered_downloads = array_filter( $downloads, function( $download ) use ( $selected_weights ) {
        $filename = pathinfo( $download->get_file(), PATHINFO_FILENAME );
        // 检查文件名是否匹配选中权重
        foreach ( $selected_weights as $weight ) {
            // PHP版本低于8.0时,替换为strpos($filename, $weight) !== false
            if ( str_contains( $filename, $weight ) ) {
                return true;
            }
        }
        return false;
    });

    return $filtered_downloads;
}

代码说明

  1. 钩子作用:woocommerce_order_item_get_downloads会在获取订单项下载文件列表时触发,允许修改返回的下载项数组。
  2. 元数据获取:通过$item->get_meta('Selected weights')读取之前保存的用户选择选项。
  3. 格式转换:如果存储的是逗号分隔字符串,转为数组方便后续匹配操作。
  4. 文件筛选:用array_filter遍历所有下载文件,检查文件名(不含扩展名)是否包含选中的权重字符串,仅保留匹配项。
  5. 版本兼容:str_contains适用于PHP 8.0+,低版本PHP可替换为strpos($filename, $weight) !== false。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 17:25:00