dongya4335 2018-10-04 19:23
浏览 111
已采纳

Woocommerce:在class-wc-product-variable.php文件中为foreach()提供的参数无效

I'm creating a type of variable product customized for my theme, I've managed to appear in the dropdown of product data and that can be saved without causing conflict. The problem is that seeing the product in frontend gives me the following error:

Warning: Invalid argument supplied for foreach() in /Applications/MAMP/htdocs/canopy/wp-content/plugins/Woocommerce/includes/class-wc-product-variable.php on line 83

I have traced the problem to the file Wordpress/includes/data-stores/class-wc-product-variable-data-store-cpt.php but the truth is that I do not know what else to do.

I leave the code that I wrote for this:

WC_Product_variable_canopytour.php

class WC_Product_Variable_CanopyTour extends WC_Product_Variable {
    public function __construct( $product ) {
        $this->product_type = 'variable_canopytour';
        parent::__construct( $product );
    }

    public function get_type() {
        return 'variable_canopytour';
    }
}

class-woocommerce-custom-product.php

class WCB_Woocommerce_CanopyTour_Product_Type {
    private $wcb;
    private $version;

    public function __construct( $wcb, $version ) {
        $this->wcb = $wcb;
        $this->version = $version;
    }

    public function register_canopytour_product_type() {
        remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 10 );

        include_once(get_template_directory() . 'woocommerce/WC_Product_variable_canopytour.php');
    }

    public function add_canopytour_product( $types ) {
        $types[ 'variable_canopytour' ] = __( 'Variable Canopy Tour', $this->wcb );
        return $types;
    }

    public function get_tour_product_class($classname, $product_type) {
        if ( $product_type === "variable_canopytour" ) {
            $classname = 'WC_Product_Variable_CanopyTour';
        }
        return $classname;
    }

    public function wcb_admin_footer() {
        if ( 'product' != get_post_type() ) :
            return;
        endif;

        ?><script type='text/javascript'>
            jQuery( document ).ready( function() {
                jQuery( '.options_group.pricing' ).addClass( 'show_if_variable_canopytour show_if_simple show_if_external' ).show();
                jQuery( 'li.general_options.general_tab' ).addClass( 'show_if_variable_canopytour show_if_simple show_if_external' ).show();
                jQuery( '.variations_options.variations_tab' ).addClass( 'show_if_variable_canopytour' ).show();
                jQuery( '.enable_variation' ).addClass( 'show_if_variable_canopytour' ).show();
            });
        </script><?php
    }

    function hide_wcb_data_panel( $tabs) {
        // Other default values for 'attribute' are; general, inventory, shipping, linked_product, variations, advanced
        $tabs['shipping']['class'][] = 'hide_if_variable_canopytour';
        return $tabs;
    }
}

functions.php

include_once get_template_directory() . 'includes/woocommerce/class-woocommerce-custom-product.php';
$woo_ct = new WCB_Woocommerce_CanopyTour_Product_Type( "wcb", "1.0" );

add_action( 'init', array($woo_ct, 'register_canopytour_product_type') );
add_filter( 'product_type_selector', array($woo_ct, 'add_canopytour_product') );
add_filter( 'woocommerce_product_class', array($woo_ct, 'get_tour_product_class'), 10, 2 ); 
add_action( 'admin_head', array($woo_ct, 'wcb_admin_head') );
add_filter( 'woocommerce_product_data_tabs', array($woo_ct, 'hide_wcb_data_panel') );

I hope someone can help me understand what happens :(

Thank you!

  • 写回答

2条回答 默认 最新

  • duanjian5059 2018-10-10 03:50
    关注

    The Problem

    You got that warning because the read_price_data() method is (as of writing) only available in the WC_Product_Variable_Data_Store_CPT class and not the default one that's used for custom product type, which is WC_Product_Data_Store_CPT.

    However, despite the default class doesn't have the read_price_data() method, calling it from the class's instance doesn't result in an exception/error because that class is instantiated through the WC_Data_Store class, which has the magic method __call().

    // Case 1: In WC_Product_Variable::get_variation_prices().
    // $this->data_store is an instance of WC_Product_Variable_Data_Store_CPT
    $prices = $this->data_store->read_price_data( $this, $for_display ); // array
    
    // Case 2: In WC_Product_Variable_CanopyTour::get_variation_prices().
    // $this->data_store is an instance of WC_Product_Data_Store_CPT
    $prices = $this->data_store->read_price_data( $this, $for_display ); // null
    

    But since the read_price_data() method is expected to return an array and yet it doesn't (or that it returns null), that's why PHP throws the "Invalid argument supplied for foreach() ..." warning:

    // The following code throws a warning.
    foreach ( null as $key => $value ) {
        ...
    }
    

    The Solution

    You need to use the proper data store class for your custom (variable) product type.

    I.e. Add an item to the WC_Data_Store::$stores array, where the key is the (variable) product type prefixed with product- (so in your case, it would be product-variable_canopytour), and the value is the class that handles the data store (e.g. WC_Product_Variable_Data_Store_CPT as in the below example).

    You can do so via the woocommerce_data_stores filter, like so: (add to the active theme's functions.php file)

    add_filter( 'woocommerce_data_stores', function( $stores ){
        $stores['product-variable_canopytour'] = 'WC_Product_Variable_Data_Store_CPT';
        return $stores;
    } );
    

    Additional Note

    The constructor for WC_Product_Variable_CanopyTour should be defined the same way the parent class defines it, where the $product is optional and that it defaults to zero (0), like so:

    class WC_Product_Variable_CanopyTour extends WC_Product_Variable {
        public function __construct( $product = 0 ) {
            $this->product_type = 'variable_canopytour';
            parent::__construct( $product );
        }
    
        ...
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥30 自适应 LMS 算法实现 FIR 最佳维纳滤波器matlab方案
  • ¥15 lingo18勾选global solver求解使用的算法
  • ¥15 全部备份安卓app数据包括密码,可以复制到另一手机上运行
  • ¥15 Python3.5 相关代码写作
  • ¥20 测距传感器数据手册i2c
  • ¥15 RPA正常跑,cmd输入cookies跑不出来
  • ¥15 求帮我调试一下freefem代码
  • ¥15 matlab代码解决,怎么运行
  • ¥15 R语言Rstudio突然无法启动
  • ¥15 关于#matlab#的问题:提取2个图像的变量作为另外一个图像像元的移动量,计算新的位置创建新的图像并提取第二个图像的变量到新的图像