无法在筛选’woocommerce_package_rates’后选择送货方式。

huangapple go评论42阅读模式
英文:

Unable to select shipping method after filtering 'woocommerce_package_rates'

问题

我刚写了这个过滤器来在有免费运输时禁用非免费运输方法:

add_filter( 'woocommerce_package_rates', 'disable_paid_shipping', 9999, 2 );
function disable_paid_shipping( $rates, $package ) {
    $free_rates = array();

    foreach ( $rates as $i => $rate ) {
        if ( str_contains( $rate->label, "gratuita" ) OR str_contains( $rate->label, "gratuito" ) ) {
            $free_rates[] = $rate;
        }

        if ( str_contains( $rate->id, "local") ) {
            $local = $rate;
        }

        if ( str_contains( $rate->id, "fermopoint") ) {
            $fermopoint = $rate;
        }
     }

    if ( !empty( $free_rates ) ) {
        if ( isset($fermopoint) ) {
            $fermopoint->cost = 0;
            $fermopoint->label .= ' gratuito';
            array_unshift( $free_rates, $fermopoint );
        }

        if ( isset($local) ) {
            $free_rates[] = $local;
        }

        $rates = $free_rates;
    } 

    return $rates;
}

该代码按预期运行,但有两个意外事件:

  1. 不再默认选择任何运输方法(无论是购物车还是结账页面)
  2. 在购物车页面中选择一个运输方式后,立即取消选择

为了解决第一个问题,在结账时,可以通过woocommerce_before_cart挂钩强制选择(尽管这看起来像是一种强制性的技巧)。

至于第二个问题,我没有想法。

有什么建议吗?

英文:

I just wrote this filter to disable non-free shipping methods when free shipping is available:

add_filter( 'woocommerce_package_rates', 'disable_paid_shipping', 9999, 2 );
function disable_paid_shipping( $rates, $package ) {
    $free_rates = array();

    foreach ( $rates as $i => $rate ) {
        if ( str_contains( $rate->label, "gratuita" ) OR str_contains( $rate->label, "gratuito" ) ) {
            $free_rates[] = $rate;
        }
    
        if ( str_contains( $rate->id, "local") ) {
            $local = $rate;
        }
    
        if ( str_contains( $rate->id, "fermopoint") ) {
            $fermopoint = $rate;
        }
     }
    
    if ( !empty( $free_rates ) ) {
        if ( isset($fermopoint) ) {
            $fermopoint->cost = 0;
            $fermopoint->label .= ' gratuito';
            array_unshift( $free_rates, $fermopoint );
        }

        if ( isset($local) ) {
            $free_rates[] = $local;
        }

        $rates = $free_rates;
    } 

    return $rates;
}

The code works as expected, unless for two unexpected events occurring:

  1. no shipping method is selected by default anymore (both in cart and checkout page)
  2. when I choose one in the cart page, it gets unselected right after (only in cart page)

To solve the 1st problem at checkout, I can work around by forcing the selection through a hook on woocommerce_before_cart (although this looks like a forced trick).

For the 2nd problem I have no idea.

Suggestions?

答案1

得分: 0

问题出在WC的$rates数组是一个关联数组:

$rates = Array ( 
              [rate_id_0] => [rate_obj_0] 
              [rate_id_1] => [rate_obj_1]
              ... 
         );

而新创建的$free_rates是一个索引数组:

$free_rates = Array ( 
              [0] => [rate_obj_0] 
              [1] => [rate_obj_1] 
              ... 
         );

因此,WC无法将新的$free_rates数组与用户的默认rate_id匹配,该默认rate_id应该用作数组键。

以下是工作代码:

add_filter( 'woocommerce_package_rates', 'disable_paid_shipping', 9999, 2 );
function disable_paid_shipping( $rates, $package ) {
    $free_rates = array();

    foreach ( $rates as $i => $rate ) {
        if ( str_contains( $rate->label, "gratuita" ) OR str_contains( $rate->label, "gratuito" ) ) {
            $free_rates[$rate->id] = $rate;
        }

        if ( str_contains( $rate->id, "local" ) ) {
            $local = $rate;
        }

        if ( str_contains( $rate->id, "fermopoint" ) ) {
            $fermopoint = $rate;
        }
     }

    if ( !empty( $free_rates ) ) {
        if ( isset($fermopoint) ) {
            $fermopoint->cost = 0;
            $fermopoint->label .= ' gratuito';
            $free_rates = array($fermopoint->id => $fermopoint) + $free_rates; // 将其设置为第一个
        }

        if ( isset($local) ) {
            $free_rates[$local->id] = $local;
        }

        $rates = $free_rates;
    } 

    return $rates;
}

请注意,这只是代码的翻译部分。如果您有任何其他问题或需要进一步的帮助,请随时提问。

英文:

The problem lies in that the WC $rates array is an associative array:

$rates = Array ( 
              [rate_id_0] => [rate_obj_0] 
              [rate_id_1] => [rate_obj_1]
              ... 
         );

While the newly created $free_rates is an indexed array:

$free_rates = Array ( 
              [0] => [rate_obj_0] 
              [1] => [rate_obj_1] 
              ... 
         );

As result, WC is unable to match the new $free_rates array with the user's default rate_id, which is supposed to be used as the array key.

Here's the working code:

add_filter( 'woocommerce_package_rates', 'disable_paid_shipping', 9999, 2 );
function disable_paid_shipping( $rates, $package ) {
    $free_rates = array();

    foreach ( $rates as $i => $rate ) {
        if ( str_contains( $rate->label, "gratuita" ) OR str_contains( $rate->label, "gratuito" ) ) {
            $free_rates[$rate->id] = $rate;
        }
    
        if ( str_contains( $rate->id, "local") ) {
            $local = $rate;
        }
    
        if ( str_contains( $rate->id, "fermopoint") ) {
            $fermopoint = $rate;
        }
     }
    
    if ( !empty( $free_rates ) ) {
        if ( isset($fermopoint) ) {
            $fermopoint->cost = 0;
            $fermopoint->label .= ' gratuito';
            $free_rates = array($fermopoint->id => $fermopoint) + $free_rates; // to set it as 1st
        }

        if ( isset($local) ) {
            $free_rates[$local->id] = $local;
        }

        $rates = $free_rates;
    } 

    return $rates;
}

huangapple
  • 本文由 发表于 2023年2月16日 19:01:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/75471306.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定