【问题标题】:Add and save custom meta data to fees in WooCommerce在 WooCommerce 中添加自定义元数据并将其保存到费用中
【发布时间】:2019-02-04 09:40:23
【问题描述】:

我正在使用 WC()->cart->add_fee() 方法向 WC 添加自定义费用。

我的问题是我也想向该费用项目添加元数据。最好在我添加实际费用的同时。

显然WC_Order_Item_Fee 对象仅在创建订单时生成,因此似乎无法将特定于 FeeItem 的元数据添加到自定义费用中。

当然我可以将这个元数据保存到会话中,但是由于 add_fee 不返回任何标识符,我不知道哪个自定义费用实际上是哪个。

任何想法如何解决这个问题?

这是我用来添加费用的代码:

add_filter('woocommerce_cart_calculate_fees', function (){
    foreach( FeeChecker::getFees() as $fee )
    {
        $cart->add_fee("Added fee: ". $fee, 10 , true, $tax_class);
    }
}

【问题讨论】:

    标签: php wordpress woocommerce cart fee


    【解决方案1】:

    注意:在您的代码中,挂钩函数中缺少 $cart 参数,它是一个动作挂钩,而不是过滤挂钩。

    WC_Cart 方法 add_fee() 不允许添加自定义元数据,因此您需要在 add_to_cart 事件或 WC_Session 之前添加它。

    您可以使用以下代码示例在提交订单时将自定义元数据添加到WC_Order_Item_Fee(在此处使用 WC_Session 设置和获取自定义元数据)

    // Add a custom cart fee
    add_action( 'woocommerce_cart_calculate_fees', 'adding_cart_fees', 10, 1 );
    function adding_cart_fees( $cart ){
        $cart->add_fee(__("Added fee"), 10, true, '');
    }
    
    // Set Fee custom meta data in WC_Session
    add_action( 'woocommerce_calculate_totals', 'calculate_totals_for_fees_meta_data', 10, 1 );
    function calculate_totals_for_fees_meta_data( $cart ){
        if ( is_admin() && ! defined( 'DOING_AJAX' ) )
            return;
    
        $fees_meta = WC()->session->get('fees_meta');
        $update    = false;
    
        // Loop through applied fees
        foreach( $cart->get_fees() as $fee_key => $fee ) {
            // Set the fee in the fee custom meta data array
            if( ! isset($fees_meta[$fee_key]) ){
                $fees_meta[$fee_key] = 'some value';
                $update = true;
            }
        }
        // If any fee meta data doesn't exist yet, we update the WC_Session custom meta data array
        if ( $update ) {
            WC()->session->set('fees_meta', $fees_meta);
        }
    }
    
    // Save fee custom meta data to WC_Order_Item_Fee.
    add_action( 'woocommerce_checkout_create_order_fee_item', 'save_custom_met_data_to_fee_order_items', 10, 4 );
    function save_custom_met_data_to_fee_order_items( $item, $fee_key, $fee, $order ) {
        // Get fee meta data from WC_Session
        $fees_meta = WC()->session->get('fees_meta');
        // If fee custom meta data exist, save it to fee order item
        if ( isset($fees_meta[$fee_key]) ) {
            $item->update_meta_data( 'custom_key', $fees_meta[$fee_key] );
        }
    }
    
    // Remove Fee meta data from WC_Session.
    add_action( 'woocommerce_checkout_create_order', 'remove_fee_custom_met_data_from_wc_session', 10, 2 );
    function remove_fee_custom_met_data_from_wc_session( $order, $data ) {
        $fees_meta = WC()->session->__unset('fees_meta');
    }
    

    代码进入您的活动子主题(或活动主题)的 function.php 文件中。经过测试并且可以工作。

    自定义元数据保存到 WC_Order_Item_Fee,您可以使用以下方式获取它:

    // Get an instance of the WC_Order Object (if needed)
    $order = wc_get_order( $order_id );
    
    // loop through fee order items
    foreach ( $order->get_items('fee') as $fee_key => $item ) {
        // Get the fee custom meta data
        $fee_custom_meta = $item->get_meta('custom_key');
    
        if ( $fee_custom_meta ) {
            // Display the custom meta data value
            echo '<p>' . $fee_custom_meta . '</p>';
        }
    }
    

    【讨论】:

    • 这实际上并不能解决问题。这里的主要用例是为每个交付包创建额外费用。每个包都会有一个自定义费用描述(因此在我的示例中是 for 循环)基本问题仍然存在。我需要一种方法来引用创建的费用,以便我知道哪些元数据属于哪个费用。我在创建费用时就知道了,但是由于费用创建不会生成任何类型的密钥,因此无法在 woocommerce_checkout_create_order_fee_item-action 中引用它。有了这个解决方案,我需要知道哪些费用是哪个费用,这是最初的问题。
    • @sarte 你的问题代码和解释很差,所以没有人应该能够猜出让它适用于你的情况的真正方法......我的回答照原样工作,让路,你的实际新代码主要是根据我的回答代码...
    【解决方案2】:

    一种有点老套的方法是使用费用项目的 ID 字段链接到存储在其他地方的数据。

    $args = array(
        'id'        => $data_id,
        'name'      => $name,
        'amount'    => (float) $amount,
        'taxable'   => false,
        'tax_class' => '',
    );
    $cart->fees_api()->add_fee( $args );
    

    稍后您可以使用钩子woocommerce_checkout_create_order_fee_item 获取数据并填充订单商品费用。就我而言:

    add_action( 'woocommerce_checkout_create_order_fee_item', array( $this, 'create_order_fee_item' ), 20, 4 );
    public function create_order_fee_item( $item, $fee_key, $fee, $order ) {
        $item->add_meta_data( 'product_id', $fee_key, true );
    }
    

    【讨论】:

      【解决方案3】:

      看来我忽略了WC_Cart-&gt;fees_api

      在那里我有实际返回创建的费用的方法,所以我知道woocommerce_checkout_create_order_fee_item 操作中的确切费用

      编辑:此代码最初主要由 LoicTheAztec 完成。我对其进行了编辑以适合我的特定用例并将其作为解决方案发布。不幸的是,他删除了可能对其他人有益的帖子。

      // Add cod fee
      add_action('woocommerce_cart_calculate_fees', function ( $cart ){
          if ( is_admin() && ! defined( 'DOING_AJAX' ) )
              return;
      
          //Make sure it's the right payment method
          if( WC()->session->chosen_payment_method == "cod"){
      
              $tax_class = '';
              $amount = 5;
      
              $session_data = [];
              foreach(  $cart->get_shipping_packages() as $package)
              {
                  $fee = $cart->fees_api()->add_fee(
      
                      array(
                          'name'      => "Additional cost: ".$package['custom_data'],
                          'amount'    => (float) $amount,
                          'taxable'   => true,
                          'tax_class' => $tax_class,
                      )
                  );
      
                  $session_data [ $fee->id ] = $package['custom_data'];
              }
      
              WC()->session->set('COD_fee_meta', $session_data);
      
          }
      
      }, 10, 2);
      
      // Save fee custom meta data to WC_Order_Item_Fee.
      add_action( 'woocommerce_checkout_create_order_fee_item', function ( $item, $fee_key, $fee, $order ) {
          // Get fee meta data from WC_Session
          $fees_meta = WC()->session->get('COD_fee_meta');
      
          // If fee custom meta data exist, save it to fee order item
          if ( isset($fees_meta[$fee_key]) ) {
              $item->update_meta_data( '_custom_data', $fees_meta[$fee_key] );
          }
      
      }, 10, 4 );
      
      // Remove Fee meta data from WC_Session.
      add_action( 'woocommerce_checkout_create_order', function ( $order, $data ) {
          WC()->session->__unset('COD_fee_meta');
      }, 10, 2 );
      

      【讨论】:

      • 感谢 LoicTheAztec 为我指明正确的方向。
      • 对此感到非常抱歉。我不是故意让你难过的。正如我在留给您的解决方案的评论中解释的那样,您提供的原始代码实际上并没有解决我遇到的问题。是的,我借用了一些你的代码,但它们之间有明显的区别。但我会编辑我的解决方案并在会话部分为您添加功劳。
      • 我所有的代码总是经过测试并且可以工作......您在问题中提供了非常糟糕的通用代码和解释(您没有告诉任何关于 COD 的内容)。您的新工作代码主要基于我的答案代码,应该对您的问题进行编辑,因为没有我的答案,您无法自己制作。所以我的回答应该被接受,因为它可以正常工作,并为您提供使其适用于您的案例并且对社区有用的方法。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-09-15
      • 2021-05-21
      • 2015-06-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-04
      • 1970-01-01
      相关资源
      最近更新 更多