I am trying to add a custom field to each item that I am manually adding to the cart. The custom field is a print ID that is passed back from a third party API.
This needs to be attached to each item in the cart so they can be used once the order has been paid for.
I am trying setting the custom field for each cart item using $cart_item_data when manually adding to the cart. I am not sure if this is what I need to do but god loves a trier :)
$woocommerce->cart->add_to_cart( $product_id, 1, '', '', array(printJobId => 12345) );
When I view the order in woocommerce I cant see the printJobId anywhere.
Does anyone know where I am going wrong?
Thanks
You need two other hook :
add_action( 'woocommerce_get_cart_item_from_session', 'cart_item_from_session' , 99, 2 );
function cart_item_from_session( $data, $values ) {
$data[ 'printJobId' ] = isset( $values[ 'printJobId' ] ) ? $values[ 'printJobId' ] : '';
return $data;
}
add_filter( 'woocommerce_add_order_item_meta', 'add_item_meta_order', 10, 3 );
function add_item_meta_order( $item_id, $values ) {
if ( !is_null( $values[ 'printJobId' ] ) ) {
wc_add_order_item_meta( $item_id, 'printJobId', $values[ 'printJobId' ] );
}
}
Then you will see the meta data on the backoffice and also on the order-details page
Related
In Woocommerce, I used jQuery to calculate a custom price on a single product pages, and now need to pass this value to the cart.
The desired behavior is to pass the new price retrieved from the hidden field to the cart item price.
Here is my actual code:
// Hidden input field in single product page
add_action( 'woocommerce_before_add_to_cart_button', 'custom_hidden_product_field', 11, 0 );
function custom_hidden_product_field() {
echo '<input type="hidden" id="hidden_field" name="custom_price" class="custom_price" value="">';
}
// The code to pass this data to the cart:
add_action( 'woocommerce_add_cart_item_data', 'save_custom_fields_data_to_cart', 10, 2 );
function save_custom_fields_data_to_cart( $cart_item_data, $product_id ) {
if( ! empty( $_REQUEST['custom_price'] ) ) {
// Set the custom data in the cart item
$cart_item_data['custom_data']['custom_price'] = $_REQUEST['custom_price'];
$data = array( 'custom_price' => $_REQUEST['custom_price'] );
// below statement make sure every add to cart action as unique line item
$cart_item_data['custom_data']['unique_key'] = md5( microtime().rand() );
WC()->session->set( 'custom_data', $data );
}
return $cart_item_data;
}
And check both $data and $cart_item_data to see that they both return the custom_price data that is calculated on the page.
However, I go to view cart, and the value of the line item is still 0.
I set a var equal to the WC()->session->set( 'custom_data', $data ); and then var_dump to check it, but this returns NULL which might just be what it returns, I'm not entirely sure because I've never used it.
I should also add that I have the regular_price in the product backend set to 0. When I erase this (and leave it blank) I get back the error:
Warning: A non-numeric value encountered in
C:\xampp\htdocs\my-transfer-source\wp-content\plugins\woocommerce\includes\class-wc-discounts.php on line 85
I'm wondering if I've missed something here, and if someone could lend some light onto this? Thanks
Update 2021 - Handling custom price item in mini cart
First for testing purpose we add a price in the hidden input field as you don't give the code that calculate the price:
// Add a hidden input field (With a value of 20 for testing purpose)
add_action( 'woocommerce_before_add_to_cart_button', 'custom_hidden_product_field', 11 );
function custom_hidden_product_field() {
echo '<input type="hidden" id="hidden_field" name="custom_price" class="custom_price" value="20">'; // Price is 20 for testing
}
Then you will use the following to change the cart item price (WC_Session is not needed):
// Save custom calculated price as custom cart item data
add_filter( 'woocommerce_add_cart_item_data', 'save_custom_fields_data_to_cart', 10, 2 );
function save_custom_fields_data_to_cart( $cart_item_data, $product_id ) {
if( isset( $_POST['custom_price'] ) && ! empty( $_POST['custom_price'] ) ) {
// Set the custom data in the cart item
$cart_item_data['custom_price'] = (float) sanitize_text_field( $_POST['custom_price'] );
// Make each item as a unique separated cart item
$cart_item_data['unique_key'] = md5( microtime().rand() );
}
return $cart_item_data;
}
// For mini cart
add_action( 'woocommerce_cart_item_price', 'filter_cart_item_price', 10, 2 );
function filter_cart_item_price( $price, $cart_item ) {
if ( isset($cart_item['custom_price']) ) {
$args = array( 'price' => floatval( $cart_item['custom_price'] ) );
if ( WC()->cart->display_prices_including_tax() ) {
$product_price = wc_get_price_including_tax( $cart_item['data'], $args );
} else {
$product_price = wc_get_price_excluding_tax( $cart_item['data'], $args );
}
return wc_price( $product_price );
}
return $price;
}
// Updating cart item price
add_action( 'woocommerce_before_calculate_totals', 'change_cart_item_price', 30, 1 );
function change_cart_item_price( $cart ) {
if ( ( is_admin() && ! defined( 'DOING_AJAX' ) ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ) {
// Set the new price
if( isset($cart_item['custom_price']) ){
$cart_item['data']->set_price($cart_item['custom_price']);
}
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
I working on a WordPress website where users can purchase a membership and I want to Show that if a user is a member how much he can save. I'm using ACF.
My Question is how can I show ACF field on a checkout page next to product???
WordPress in general and WooCommerce have the thing called "Hook" to help us add our custom data.
This article is an introduction and example about WooCommerce Hooks
This is a virtual version of hooks on the WooCommerce checkout page.
So as your needs, you may use woocommerce_review_order_before_cart_contents hook, add this code to functions.php file in your theme:
Add to the checkout page in general
add_action( 'woocommerce_review_order_before_cart_contents', 'add_member_info' );
function add_member_info() {
echo '<div class=”member-message”>Become a member will save $100</div>';
}
Get data from a custom field in the product
I. To show in the single product
function cw_change_product_price_display( $price, $product ) {
$my_field = get_field('member_save', $product->ID);
$price .= " | Member save $$my_field";
return $price;
}
add_filter( 'woocommerce_get_price_html', 'cw_change_product_price_display', 10, 2);
add_filter( 'woocommerce_cart_item_price', 'cw_change_product_price_display', 10, 2);
II. To show in the checkout page
Add custom data with the product to Card
add_filter( 'woocommerce_add_cart_item_data', function ( $cartItemData, $productId, $variationId ) {
$member_saved = get_field('member_save', $productId);
$cartItemData['myCustomData'] = $member_saved;
return $cartItemData;
}, 10, 3 );
add_filter( 'woocommerce_get_cart_item_from_session', function ( $cartItemData, $cartItemSessionData, $cartItemKey ) {
if ( isset( $cartItemSessionData['myCustomData'] ) ) {
$cartItemData['myCustomData'] = $cartItemSessionData['myCustomData'];
}
return $cartItemData;
}, 10, 3 );
Show the data in the cart and checkout page
add_filter( 'woocommerce_get_item_data', function ( $data, $cartItem ) {
if ( isset( $cartItem['myCustomData'] ) ) {
$data[] = array(
'name' => 'Member saved',
'value' => $cartItem['myCustomData']
);
}
return $data;
}, 10, 2 );
I am working on a wordpress project and I want to add the bulk action on my custom post.
I have used Custom Post Type UI plugin for custom post and Advanced Custom Fields plugin for custom fields.
Please suggest me any code or plugin to add bulk action for my custom posts.
Thanks,
Aniket.
Since WordPress 4.7 (released December 2016) it is possible to add custom bulk actions without using JavaScript.
//Hooks
add_action( 'current_screen', 'my_bulk_hooks' );
function my_bulk_hooks() {
if( current_user_can( 'administrator' ) ) {
add_filter( 'bulk_actions-edit-post', 'register_my_bulk_actions' );
add_filter( 'handle_bulk_actions-edit-post', 'my_bulk_action_handler', 10, 3 );
add_action( 'admin_notices', 'my_bulk_action_admin_notice' );
}
}
//Register
function register_my_bulk_actions($bulk_actions) {
$bulk_actions['email_to_eric'] = __( 'Email to Eric', 'text_domain');
return $bulk_actions;
}
//Handle
function my_bulk_action_handler( $redirect_to, $doaction, $post_ids ) {
if ( $doaction !== 'email_to_eric' ) {
return $redirect_to;
}
foreach ( $post_ids as $post_id ) {
// Perform action for each post.
}
$redirect_to = add_query_arg( 'bulk_emailed_posts', count( $post_ids ), $redirect_to );
return $redirect_to;
}
//Notices
function my_bulk_action_admin_notice() {
if ( ! empty( $_REQUEST['bulk_emailed_posts'] ) ) {
$emailed_count = intval( $_REQUEST['bulk_emailed_posts'] );
printf( '<div id="message" class="updated fade">' .
_n( 'Emailed %s post to Eric.',
'Emailed %s posts to Eric.',
$emailed_count,
'text_domain'
) . '</div>', $emailed_count );
}
}
Note.1: You must use bulk_actions filters when WP_Screen object is defined.That's why I used current_screen action in line 2.
Note.2: if you want to add bulk action to custom page like woocommerce products page just change screen id in line 5 & 6. Ex:
add_filter( 'bulk_actions-edit-product', 'register_my_bulk_actions' );
add_filter( 'handle_bulk_actions-edit-product', 'my_bulk_action_handler', 10, 3 );
More information :
Using Custom Bulk Actions
https://make.wordpress.org/core/2016/10/04/custom-bulk-actions/
use "register_post_type" of WordPress function, It easier than the additional plugins
Reference: https://codex.wordpress.org/Function_Reference/register_post_type
Im adding a custom item meta to every item with woocommerce_add_order_item_meta action.
I dont need to show this custom meta in the Order Detail, because it's an arry stringy that im using to print a pdf.
How can i remove this meta custom item? Is there some action to do it?
Thanks
I understand its a bit old question but I am answering for some other users who will have same issue in future.
If you want your order item meta to not display in admin order details page than you should append underscore (_) at the start of your meta name.
Example:
_custom_order_meta
The underscore trick no longer works. In Woo 3.x there is a hidden meta array:
add_filter('woocommerce_hidden_order_itemmeta',
array($this, 'hidden_order_itemmeta'), 50);
function hidden_order_itemmeta($args) {
$args[] = 'my_hidden_meta';
return $args;
}
It sounds like you need to keep it in order to print the PDF. If you override the order-details.php template you can possibly change:
$item_meta = new WC_Order_Item_Meta( $item['item_meta'], $_product );
to
$array = $item['item_meta'];
if( isset( $array['your_pdf_array_key'] ) ){ unset( $array['your_pdf_array_key'] ); }
$item_meta = new WC_Order_Item_Meta( $array, $_product );
EDIT
The wc_add_order_item_meta() function has 4 parameters as seen in the code:
function wc_add_order_item_meta( $item_id, $meta_key, $meta_value, $unique = false ) {
return add_metadata( 'order_item', $item_id, $meta_key, $meta_value, $unique );
}
If you choose a $meta_key with a preceding underscore, the meta will be automatically hidden from view on the checkout/order-received page, the My Order's list of the My account area, as well as in the admin's order overview page.
Therefore, I would suggest making your woocommerce_add_order_item_meta callback function look something like the following:
add_action( 'woocommerce_add_order_item_meta', '25979024_add_order_item_meta', 10, 3 );
function 25979024_add_order_item_meta( $order_item_id, $cart_item, $cart_item_key ) {
wc_add_order_item_meta( $order_item_id, '_pdf_something', 'hide this stuff' );
}
We need to get the text input from Add to cart page in cart_session and display it in the view cart page and save those in database too. I tried to add it in:
$this->cart_contents[$cart_item_key] = apply_filters( 'woocommerce_add_cart_item', array_merge( $cart_item_data, array('' => '','custom_text' => $_POST['custom_txt']) ), $cart_item_key );
It is saving the custom_txt one time and it clears it when the next product is added to cart. I think we need to do something to for save those in session. Please help us.
I assume you have one (or more) fields in "Single Product" page and you want to insert the values from that (or those) field(s) inside the cart. In my one project I used the following code that might help you. You need to customize as your need.
// Add to cart
add_filter( 'woocommerce_add_cart_item', 'woocommerce_add_cart_item_custom' );
// Add item data to the cart
add_filter( 'woocommerce_add_cart_item_data', 'woocommerce_add_cart_item_data_custom', 10, 2 );
// Load cart data per page load
add_filter( 'woocommerce_get_cart_item_from_session', 'woocommerce_get_cart_item_from_session_custom', 20, 2 );
// Get item data to display
add_filter( 'woocommerce_get_item_data', 'woocommerce_get_item_data_custom', 10, 2 );
// Validate when adding to cart
add_filter( 'woocommerce_add_to_cart_validation', 'woocommerce_add_to_cart_validation_custom', 10, 3 );
// Add meta to order
add_action( 'woocommerce_add_order_item_meta', 'woocommerce_add_order_item_meta_custom', 10, 2 );
// order again
add_filter( 'woocommerce_order_again_cart_item_data', 'woocommerce_order_again_cart_item_data', 10, 3 );
// add to cart
function woocommerce_add_cart_item_custom( $cart_item ) {
// operation done while item is added to cart.
return $cart_item;
}
// get cart from session
function woocommerce_get_cart_item_from_session_custom( $cart_item, $values ) {
if (!empty($values['cusotm_field'])) :
$cart_item['cusotm_field'] = $values['cusotm_field'];
$cart_item = woocommerce_add_cart_item_custom( $cart_item );
endif;
return $cart_item;
}
// get item data
function other_options_get_item_data( $other_data, $cart_item ) {
if (!empty($cart_item['custom_option'])) :
$other_data = array(
'name' => $custom,
'value' => $value,
'display' => $custom .' : '.$value
);
endif;
return $other_data;
}
function woocommerce_add_cart_item_data_custom($cart_item_meta, $product_id){
global $woocommerce;
if(empty($cart_item_meta['custom_field']))
$cart_item_meta['custom_field'] = array();
$cart_item_meta['custom_field'] = esc_attr($_POST[sanitize_title('name_of_field')]);
return $cart_item_meta;
}
// add to order meta
function woocommerce_add_order_item_meta_custom( $item_id, $values ) {
if ( ! empty( $values['custom_option'] ) ) {
woocommerce_add_order_item_meta( $item_id, $option_name, $option_value );
}
}
// validation
function woocommerce_add_to_cart_validation_custom($passed, $product_id, $qty){
global $woocommerce;
$option = ''; // your custom field's name
if( isset($_POST[sanitize_title($option)]) && $_POST[sanitize_title($option)] == '' )
$passed = false;
if (!$passed)
$woocommerce->add_error( sprintf( __('"%s" is a required field.', 'woocommerce'), $option) );
return $passed;
}
function woocommerce_order_again_cart_item_data($cart_item_meta, $product, $order){
global $woocommerce;
// Disable validation
remove_filter( 'woocommerce_add_to_cart_validation', array( $this, 'validate_add_cart_item' ), 10, 3 );
if(empty($cart_item_meta['custom_field']))
$cart_item_meta['custom_field'] = array();
$cart_item_meta['_other_options']= esc_attr($_POST[sanitize_title('field_name')]);
return $cart_item_meta;
}
This is a very general code. you need to modify that best suites you need.
Thanks.