Home › Forums › Front-end Issues › Price field as WooCommerce price
I’ve seen online that you can add all Custom Post Types to a WooCommerce cart as long as the CPT has a price field. The only issue is that you have to tell WooCommerce what CPT field contains the price.
Afterwords you can create an add-to-cart url like this:
https://yourdomain.com/?add-to-cart=XXX (XXX being the Custom Post Type post ID)
Why is this handy?
I have an online menu (just to inform guest what we order) but because of Corona we have to close our doors so I want these dishes to be ordered online.
The code should be something like this but the CPT is not added to cart:
add_filter('woocommerce_get_price', 'yl_get_dish_price', 20,2);
function yl_get_dish_price($price,$post) {
if ($post->post->post_type === 'dish') {
$price = get_field('price', $post->ID);
}
return $price;
}
The following code adds the CPT (dish in my case) to the WooCommerce cart but the price is incorrect. It always displays € 10,00
class YL_Dish_Product extends WC_Product {
protected $post_type = 'dish';
public function get_type() {
return 'dish';
}
public function __construct( $product = 0 ) {
$this->supports[] = 'ajax_add_to_cart';
parent::__construct( $product );
}
// maybe overwrite other functions from WC_Product
}
class YL_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 || 'dish' !== $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 YL_WC_Order_Item_Product extends WC_Order_Item_Product {
public function set_product_id( $value ) {
if ( $value > 0 && 'dish' !== 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 YL_woocommerce_data_stores( $stores ) {
// the search is made for product-$post_type so note the required 'product-' in key name
$stores['product-dish'] = 'YL_Data_Store_CPT';
return $stores;
}
add_filter( 'woocommerce_data_stores', 'YL_woocommerce_data_stores' , 11, 1 );
function YL_woo_product_class( $class_name , $product_type , $product_id ) {
if ($product_type == 'dish')
$class_name = 'YL_Dish_Product';
return $class_name;
}
add_filter('woocommerce_product_class','YL_woo_product_class',25,3 );
function my_woocommerce_product_get_price( $price, $product ) {
if ($product->get_type() == 'dish' ) {
$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 YL_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 == 'dish' && $post->ID == $product_id)
return 'dish';
else {
$product = get_post( $product_id );
if (is_object($product) && !is_wp_error($product)) { // post not set but it's a dish
if ($product->post_type == 'dish')
return 'dish';
} // 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 == 'dish')
return 'dish';
} else {
$product = get_post( $product_id );
if (is_object($product) && !is_wp_error($product)) { // post not set but it's a dish
if ($product->post_type == 'dish')
return 'dish';
} // end if
} // end if // end if
} // end if
return false;
}
add_filter('woocommerce_product_type_query','YL_woo_product_type',12,2 );
function YL_woocommerce_checkout_create_order_line_item_object($item, $cart_item_key, $values, $order) {
$product = $values['data'];
if ($product->get_type() == 'dish') {
return new YL_WC_Order_Item_Product();
} // end if
return $item ;
}
add_filter( 'woocommerce_checkout_create_order_line_item_object', 'YL_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() == 'dish') {
$item->update_meta_data( '_dish', '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 YL_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 = '_dish'");
if ('yes' === $is_IA) { // load the new class if the item is our custom post
$classname = 'YL_WC_Order_Item_Product';
} // end if
return $classname;
}
add_filter( 'woocommerce_get_order_item_classname', 'YL_woocommerce_get_order_item_classname', 20, 3 );
Any idea how to get the price field right? This doesn’t work:
add_filter('woocommerce_get_price', 'yl_get_dish_price', 20,2);
function yl_get_dish_price($price,$post) {
if ($post->post_type === 'dish') {
$price = get_field('price', $post->ID);
}
return $price;
}
add_filter( 'woocommerce_product_get_price', 'yl_get_dish_price', 20, 2 );
add_filter( 'woocommerce_product_get_regular_price', 'yl_get_dish_price', 20, 2 );
function yl_get_dish_price( $price, $product ) {
if ( $product->is_type('dish') ) {
$price = get_field( 'price', $product->get_id() );
}
return $price;
}
You must be logged in to reply to this topic.
Welcome to the Advanced Custom Fields community forum.
Browse through ideas, snippets of code, questions and answers between fellow ACF users
Helping others is a great way to earn karma, gain badges and help ACF development!
We use cookies to offer you a better browsing experience, analyze site traffic and personalize content. Read about how we use cookies and how you can control them in our Privacy Policy. If you continue to use this site, you consent to our use of cookies.