woocommerce 将自定义帖子类型添加到购物车

So-*_*mar 2 php wordpress woocommerce

我正在使用 woocommerce,并且创建了一个自定义帖子类型,该类型必须被视为产品,并且用户可以添加到购物车。我按照本教程 \n http://reigelgallarde.me/programming/how-to-add-custom-post-type-to-woocommerce/ \n 并确保我的价格字段元键是 \xe2\x80\x9c_price\xe2 \x80\x9d\n但是没用。

\n\n

当我尝试将此代码添加到functions.php时

\n\n
function reigel_woocommerce_get_price($price = null,$post = null){\nif ($post->post->post_type === \'aytam\'){\n    $price = get_post_meta($post->id, "_price", true);\n    }\n\nreturn $price;\n}\nadd_filter(\'woocommerce_get_price\',\'reigel_woocommerce_get_price\',20,1);\nadd_action( \'init\', \'reigel_woocommerce_get_price\' );\n
Run Code Online (Sandbox Code Playgroud)\n\n

也没用

\n

Sha*_*med 6

在最新版本3.0.* Woocommcerce 用于硬检查$post_type === 'product'您可以覆盖它。您可以在这里找到完整的解决方案。

class My_Product_Data_Store_CPT extends WC_Product_Data_Store_CPT implements WC_Object_Data_Store_Interface, WC_Product_Data_Store_Interface {

    
    /**
     * Method to read a product from the database.
     * @param WC_Product
     */
    public function read( &$product ) {
        $product->set_defaults();

        if ( ! $product->get_id() || ! ( $post_object = get_post( $product->get_id() ) ) || 'product' !== $post_object->post_type ) {
            //throw new Exception( __( 'Invalid product.', 'woocommerce' ) );
        }

        $id = $product->get_id();

        $product->set_props( array(
            'name'              => $post_object->post_title,
            'slug'              => $post_object->post_name,
            'date_created'      => 0 < $post_object->post_date_gmt ? wc_string_to_timestamp( $post_object->post_date_gmt ) : null,
            'date_modified'     => 0 < $post_object->post_modified_gmt ? wc_string_to_timestamp( $post_object->post_modified_gmt ) : null,
            'status'            => $post_object->post_status,
            'description'       => $post_object->post_content,
            'short_description' => $post_object->post_excerpt,
            'parent_id'         => $post_object->post_parent,
            'menu_order'        => $post_object->menu_order,
            'reviews_allowed'   => 'open' === $post_object->comment_status,
        ) );

        $this->read_attributes( $product );
        $this->read_downloads( $product );
        $this->read_visibility( $product );
        $this->read_product_data( $product );
        $this->read_extra_data( $product );
        $product->set_object_read( true );
    }

    
}
Run Code Online (Sandbox Code Playgroud)

然后通过钩子包含这个文件;

add_filter( 'woocommerce_data_stores', 'my_woocommerce_data_stores' );

function my_woocommerce_data_stores( $stores ) {

    require_once PLUGIN_PATH . '/includes/classes/class-data-store-cpt.php';
    $stores['product'] = 'MY_Product_Data_Store_CPT';

    return $stores;
}
Run Code Online (Sandbox Code Playgroud)

使用此过滤器提供自定义元的价格;

add_filter('woocommerce_product_get_price', 'my_woocommerce_product_get_price', 10, 2 );
function my_woocommerce_product_get_price( $price, $product ) {

    if (get_post_type($product->get_id()) == 'book' ) {
        $price = get_post_meta( $product->get_id(), 'price', true );
    }
    return $price;
}
Run Code Online (Sandbox Code Playgroud)

现在,如果您尝试使用add-to-cart=[POST_ID]http://localhost/wordpress/cart/?add-to-cart=244 等 url 参数添加到购物车,则会将商品添加到购物车。

您还可以使用按钮添加到购物车。

        <form action="" method="post">
            <input name="add-to-cart" type="hidden" value="<?php the_ID(); ?>" />
            <input name="quantity" type="number" value="1" min="1"  />
            <input name="submit" type="submit" value="Add to cart" />
        </form>
Run Code Online (Sandbox Code Playgroud)


cod*_*ize 5

一直在解决这个问题,由于上面的代码不起作用,我继续制作了一个工作版本。请注意,此代码适用于Woocommerce 3.6.2(至少),旨在使其适用于自定义帖子类型Industry-ad,但您可以更改为您想要的内容

class IA_Woo_Product extends WC_Product  {

    protected $post_type = 'industry-ad';

    public function get_type() {
        return 'industry-ad';
    }

    public function __construct( $product = 0 ) {
        $this->supports[]   = 'ajax_add_to_cart';

        parent::__construct( $product );


    }
    // maybe overwrite other functions from WC_Product

}

class IA_Data_Store_CPT extends WC_Product_Data_Store_CPT {

    public function read( &$product ) { // this is required
        $product->set_defaults();
        $post_object = get_post( $product->get_id() );

        if ( ! $product->get_id() || ! $post_object || 'industry-ad' !== $post_object->post_type ) {

            throw new Exception( __( 'Invalid product.', 'woocommerce' ) );
        }

        $product->set_props(
            array(
                'name'              => $post_object->post_title,
                'slug'              => $post_object->post_name,
                'date_created'      => 0 < $post_object->post_date_gmt ? wc_string_to_timestamp( $post_object->post_date_gmt ) : null,
                'date_modified'     => 0 < $post_object->post_modified_gmt ? wc_string_to_timestamp( $post_object->post_modified_gmt ) : null,
                'status'            => $post_object->post_status,
                'description'       => $post_object->post_content,
                'short_description' => $post_object->post_excerpt,
                'parent_id'         => $post_object->post_parent,
                'menu_order'        => $post_object->menu_order,
                'reviews_allowed'   => 'open' === $post_object->comment_status,
            )
        );

        $this->read_attributes( $product );
        $this->read_downloads( $product );
        $this->read_visibility( $product );
        $this->read_product_data( $product );
        $this->read_extra_data( $product );
        $product->set_object_read( true );
    }

    // maybe overwrite other functions from WC_Product_Data_Store_CPT

}


class IA_WC_Order_Item_Product extends WC_Order_Item_Product {
    public function set_product_id( $value ) {
        if ( $value > 0 && 'industry-ad' !== get_post_type( absint( $value ) ) ) {
            $this->error( 'order_item_product_invalid_product_id', __( 'Invalid product ID', 'woocommerce' ) );
        }
        $this->set_prop( 'product_id', absint( $value ) );
    }

}




function IA_woocommerce_data_stores( $stores ) {
    // the search is made for product-$post_type so note the required 'product-' in key name
    $stores['product-industry-ad'] = 'IA_Data_Store_CPT';
    return $stores;
}
add_filter( 'woocommerce_data_stores', 'IA_woocommerce_data_stores' , 11, 1 );


function IA_woo_product_class( $class_name ,  $product_type ,  $product_id ) {
    if ($product_type == 'industry-ad')
        $class_name = 'IA_Woo_Product';
    return $class_name; 
}
add_filter('woocommerce_product_class','IA_woo_product_class',25,3 );



function my_woocommerce_product_get_price( $price, $product ) {

    if ($product->get_type() == 'industry-ad' ) {
        $price = 10;  // or get price how ever you see fit     
    }
    return $price;
}
add_filter('woocommerce_get_price','my_woocommerce_product_get_price',20,2);
add_filter('woocommerce_product_get_price', 'my_woocommerce_product_get_price', 10, 2 );



// required function for allowing posty_type to be added; maybe not the best but it works
function IA_woo_product_type($false,$product_id) { 
    if ($false === false) { // don't know why, but this is how woo does it
        global $post;
        // maybe redo it someday?!
        if (is_object($post) && !empty($post)) { // post is set
            if ($post->post_type == 'industry-ad' && $post->ID == $product_id) 
                return 'industry-ad';
            else {
                $product = get_post( $product_id );
                if (is_object($product) && !is_wp_error($product)) { // post not set but it's a industry-ad
                    if ($product->post_type == 'industry-ad') 
                        return 'industry-ad';
                } // end if 
            }    

        } else if(wp_doing_ajax()) { // has post set (usefull when adding using ajax)
            $product_post = get_post( $product_id );
            if ($product_post->post_type == 'industry-ad') 
                return 'industry-ad';
        } else { 
            $product = get_post( $product_id );
            if (is_object($product) && !is_wp_error($product)) { // post not set but it's a industry-ad
                if ($product->post_type == 'industry-ad') 
                    return 'industry-ad';
            } // end if 

        } // end if  // end if 



    } // end if 
    return false;
}
add_filter('woocommerce_product_type_query','IA_woo_product_type',12,2 );

function IA_woocommerce_checkout_create_order_line_item_object($item, $cart_item_key, $values, $order) {

    $product                    = $values['data'];
    if ($product->get_type() == 'industry-ad') {
        return new IA_WC_Order_Item_Product();
    } // end if 
    return $item ;
}   
add_filter( 'woocommerce_checkout_create_order_line_item_object', 'IA_woocommerce_checkout_create_order_line_item_object', 20, 4 );

function cod_woocommerce_checkout_create_order_line_item($item,$cart_item_key,$values,$order) {
    if ($values['data']->get_type() == 'industry-ad') {
        $item->update_meta_data( '_industry-ad', 'yes' ); // add a way to recognize custom post type in ordered items
        return;
    } // end if 

}
add_action( 'woocommerce_checkout_create_order_line_item', 'cod_woocommerce_checkout_create_order_line_item', 20, 4 );

function IA_woocommerce_get_order_item_classname($classname, $item_type, $id) {
    global $wpdb;
    $is_IA = $wpdb->get_var("SELECT meta_value FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE order_item_id = {$id} AND meta_key = '_industry-ad'");


    if ('yes' === $is_IA) { // load the new class if the item is our custom post
        $classname = 'IA_WC_Order_Item_Product';
    } // end if 
    return $classname;
}
add_filter( 'woocommerce_get_order_item_classname', 'IA_woocommerce_get_order_item_classname', 20, 3 );
Run Code Online (Sandbox Code Playgroud)