Add checkbox to product inventory tab in WooCommerce and have the checkbox checked by default - wordpress

I got this snippet in here to add checkbox custom field which is auto set and it’s working fine.
// Displaying quantity setting fields on admin product pages
add_action( 'woocommerce_product_options_pricing', 'add_custom_field_product_options_pricing' );
function add_custom_field_product_options_pricing() {
global $product_object;
echo '</div><div class="options_group">';
$values = $product_object->get_meta('_cutom_meta_key');
woocommerce_wp_checkbox( array( // Checkbox.
'id' => '_cutom_meta_key',
'label' => __( 'Custom label', 'woocommerce' ),
'value' => empty($values) ? 'yes' : $values,
'description' => __( 'Enable this to make something.', 'woocommerce' ),
) );
}
// Save quantity setting fields values
add_action( 'woocommerce_admin_process_product_object', 'save_custom_field_product_options_pricing' );
function save_custom_field_product_options_pricing( $product ) {
$product->update_meta_data( '_cutom_meta_key', isset($_POST['_cutom_meta_key']) ? 'yes' : 'no');
}
My question: how to move this checkbox to be on the inventory tab and have the checkbox checked by default?
I’ve tried changing :
add_action( 'woocommerce_product_options_pricing', 'add_custom_field_product_options_pricing' );
to:
add_action( 'woocommerce_product_options_inventory_product_data', 'add_custom_field_product_options_pricing' );
AND
add_action( 'woocommerce_admin_process_product_object', 'save_custom_field_product_options_pricing' );
to:
add_action( 'woocommerce_process_product_meta', 'save_custom_field_product_options_pricing' );
But to no avail. Any advice?

woocommerce_admin_process_product_object replaces the outdated woocommerce_process_product_meta hook so you should definitely not replace it with it
To have the checkbox checked by default you can add value to the args from woocommerce_wp_checkbox()
So you get:
// Add checkbox
function action_woocommerce_product_options_inventory_product_data() {
global $product_object;
// Get meta
$value = $product_object->get_meta( '_cutom_meta_key' );
// Checkbox
woocommerce_wp_checkbox( array(
'id' => '_cutom_meta_key', // Required, it's the meta_key for storing the value (is checked or not)
'label' => __( 'Custom label', 'woocommerce' ), // Text in the editor label
'desc_tip' => false, // true or false, show description directly or as tooltip
'description' => __( 'Enable this to make something', 'woocommerce' ), // Provide something useful here
'value' => empty( $value ) ? 'yes' : $value // Checked by default
) );
}
add_action( 'woocommerce_product_options_inventory_product_data', 'action_woocommerce_product_options_inventory_product_data', 10, 0 );
// Save Field
function action_woocommerce_admin_process_product_object( $product ) {
// Update meta
$product->update_meta_data( '_cutom_meta_key', isset( $_POST['_cutom_meta_key'] ) ? 'yes' : 'no' );
}
add_action( 'woocommerce_admin_process_product_object', 'action_woocommerce_admin_process_product_object', 10, 1 );

Related

How to add custom button before Add to Cart form in WooCommerce Product Page and I want different links for different products?

How to add a custom button before Add to Cart form on WooCommerce Product Page? and I want different links for different products.
My PHP Code:
add_action( 'woocommerce_before_add_to_cart_form', 'learnalwayss_after_add_to_cart_btn' );
function learnalwayss_after_add_to_cart_btn() {
global $product;
if ( $product->get_id() == 149685 ) {
echo '<a class="button primary is-small box-shadow-4 box-shadow-2-hover" style="border-radius: 10px; background-color:#FFDB58 !important; color:black;" target="_blank" href="https://myurls.bio/learn_alwayss">Our Links</a>';
}
}
Your solution is simple and effective but you have to add every url manually in the source code.
The solution I am suggesting uses wp_postmeta to store the label and url of the button. This way, a regular user can add/change the value of the url instead of asking a developer to make every change.
We'll add 2 custom fields to the product page to store these values into metadata.
To add custom fields for the custom_button_url and custom_button_text metadata to the edit product page in WooCommerce, you can use the woocommerce_product_options_general_product_data hook to add the custom fields to the product data panel, and the woocommerce_process_product_meta hook to save the custom field values when the product is saved.
function custom_button_product_data_fields() {
global $post;
// Get the values of the "custom_button_url" and "custom_button_text" custom fields
$custom_button_url = get_post_meta( $post->ID, 'custom_button_url', true );
$custom_button_text = get_post_meta( $post->ID, 'custom_button_text', true );
// Add a custom field for the "custom_button_url" metadata
woocommerce_wp_text_input( array(
'id' => 'custom_button_url',
'label' => __( 'Custom Button URL', 'your-text-domain' ),
'placeholder' => 'http://',
'description' => __( 'Enter the URL for the custom button.', 'your-text-domain' ),
'type' => 'url',
'value' => $custom_button_url,
'custom_attributes' => array(
'pattern' => 'https?://.+',
),
) );
// Add a custom field for the "custom_button_text" metadata
woocommerce_wp_text_input( array(
'id' => 'custom_button_text',
'label' => __( 'Custom Button Text', 'your-text-domain' ),
'placeholder' => '',
'description' => __( 'Enter the text for the custom button.', 'your-text-domain' ),
'type' => 'text',
'value' => $custom_button_text,
) );
}
add_action( 'woocommerce_product_options_general_product_data', 'custom_button_product_data_fields' );
And to save the values into the wp_postmeta you can use woocommerce_process_product_meta hook
function save_custom_button_product_data_fields( $post_id ) {
// Save the value of the "custom_button_url" custom field
$custom_button_url = isset( $_POST['custom_button_url'] ) ? sanitize_text_field( $_POST['custom_button_url'] ) : '';
update_post_meta( $post_id, 'custom_button_url', $custom_button_url );
// Save the value of the "custom_button_text" custom field
$custom_button_text = isset( $_POST['custom_button_text'] ) ? sanitize_text_field( $_POST['custom_button_text'] ) : '';
update_post_meta( $post_id, 'custom_button_text', $custom_button_text );
}
add_action( 'woocommerce_process_product_meta', 'save_custom_button_product_data_fields' );
Now we only have to display the button using the woocommerce_before_add_to_cart_form hook. You can use any other hook on the product page to show the button in a different place.
function custom_button_before_add_to_cart() {
global $product;
$product_id = $product->get_id();
// Get the values of the "custom_button_url" and "custom_button_text" custom fields
$custom_button_url = get_post_meta( $product_id, 'custom_button_url', true );
$custom_button_text = get_post_meta( $product_id, 'custom_button_text', true );
// If the "custom_button_url" custom field has a value, show the button
if ( ! empty( $custom_button_url ) ) {
// If the "custom_button_text" custom field has a value, use it as the button text
if ( ! empty( $custom_button_text ) ) {
$button_text = $custom_button_text;
} else {
// If the "custom_button_text" custom field is empty, use the default button text
$button_text = __( 'Default Button Text', 'your-text-domain' );
}
// Use the value of the "custom_button_url" custom field as the button link
$button_link = $custom_button_url;
echo '' . esc_html( $button_text ) . '';
}
}
add_action( 'woocommerce_before_add_to_cart_form', 'custom_button_before_add_to_cart' );
This code enables you to use WordPress or ACF custom fields to add unique button links.
add_action( 'woocommerce_before_add_to_cart_form', 'button_custom_field' );
function button_custom_field() {
$wp = get_post_meta( get_the_ID(), 'wp_button', true );
$acf = class_exists('acf') ? get_field('acf_button') : '';
$field = $acf ? $acf : $wp;
if ( $field && is_singular('product') ) {
printf( '' . __( 'Custom Button' ) . '', $field );
}
}
Note : I wouldn't add the styling inline. Better to add it in your child themes stylesheet. Source

How to add a existing custom checkout field in the account details tab - WooCommerce

I have created a custom checkout select field with validation. I was able to show this field in the order in the backend and in the confirmation email. I added it with this code:
/*** ADD DOCKING STATION FIELD # WC CHECKOUT ***/
add_action( 'woocommerce_after_checkout_billing_form', 'bbloomer_add_custom_checkout_field' );
function bbloomer_add_custom_checkout_field( $checkout ) {
$current_user = wp_get_current_user();
$saved_docking_station = $current_user->docking_station;
woocommerce_form_field( 'docking_station', array(
'type' => 'select',
'class' => array( 'form-row-wide' ),
'label' => 'Do you have a docking station/ loading dock on-site?',
'required' => true,
'default' => $saved_docking_station,
'options' => array(
'' => __( 'Choose an option' ),
'No' => __( 'No' ),
'Yes' => __( 'Yes' ),
)
), $checkout->get_value( 'docking_station' ) );
}
/* Validate this field */
add_action( 'woocommerce_checkout_process', 'bbloomer_validate_new_checkout_field' );
function bbloomer_validate_new_checkout_field() {
if ( ! $_POST['docking_station'] ) {
wc_add_notice( '<strong>Docking station</strong> is a required field.', 'error' );
}
}
/* Save & show this field # WC orders & emails */
add_action( 'woocommerce_checkout_update_order_meta', 'bbloomer_save_new_checkout_field' );
function bbloomer_save_new_checkout_field( $order_id ) {
if ( $_POST['docking_station'] ) update_post_meta( $order_id, '_docking_station', esc_attr( $_POST['docking_station'] ) );
}
add_action( 'woocommerce_admin_order_data_after_billing_address', 'bbloomer_show_new_checkout_field_order', 10, 1 );
function bbloomer_show_new_checkout_field_order( $order ) {
$order_id = $order->get_id();
if ( get_post_meta( $order_id, '_docking_station', true ) ) echo '<p><strong>Docking station:</strong> ' . get_post_meta( $order_id, '_docking_station', true ) . '</p>';
}
add_action( 'woocommerce_email_after_order_table', 'bbloomer_show_new_checkout_field_emails', 20, 4 );
function bbloomer_show_new_checkout_field_emails( $order, $sent_to_admin, $plain_text, $email ) {
if ( get_post_meta( $order->get_id(), '_docking_station', true ) ) echo '<p><strong>Docking station:</strong> ' . get_post_meta( $order->get_id(), '_docking_station', true ) . '</p>';
}
I also want to show this field on the account page; in the tab Account details (/my-account/edit-account). It would be perfect if the value of the docking field is visible on the account page and that the users can change this value on the account page for future orders.
I wonder if it's even possible to show the exact same field on the account page? I can imagine that this is not possible because checkout fields and account (user) fields are different type of fields and therefore you can't use the same field for both purposes. However, I hope it's possible.

Add custom field to product inventory tab and display value on single product page where meta ends

I'm using the following code in my theme functions.php file to add a additional data field to the product inventory tab:
// Add Custom Field to woocommerce inventory tab for product
add_action('woocommerce_product_options_inventory_product_data', function() {
woocommerce_wp_text_input([
'id' => '_number_in_package',
'label' => __('Number of Pages', 'txtdomain'),
'type' => 'number',
]);
});
add_action('woocommerce_process_product_meta', function($post_id) {
$product = wc_get_product($post_id);
$num_package = isset($_POST['_number_in_package']) ? $_POST['_number_in_package'] : '';
$product->update_meta_data('_number_in_package', sanitize_text_field($num_package));
$product->save();
});
add_action('woocommerce_product_meta_start', function() {
global $post;
$product = wc_get_product($post->ID);
$num_package = $product->get_meta('_number_in_package');
if (!empty($num_package)) {
printf('<div class="custom-sku">%s: %s</div>', __('Number of Pages', 'txtdomain'), $num_package);
}
});
add_filter('woocommerce_product_data_tabs', function($tabs) {
$tabs['additional_info'] = [
'label' => __('Additional info', 'txtdomain'),
'target' => 'additional_product_data',
'class' => ['hide_if_external'],
'priority' => 25
];
return $tabs;
});
However, on the single product page, the custom field is added before category and ISBN. I want to place the custom field at the end after the product ISBN. Any advice?
Some comments/suggestions regarding your code attempt
To save fields you can use the woocommerce_admin_process_product_object hook, opposite the outdated woocommerce_process_product_meta hook
WooCommerce contains by default no ISBN field, but it looks like the woocommerce_product_meta_end hook will answer your question
So you get:
// Add custom field
function action_woocommerce_product_options_inventory_product_data() {
woocommerce_wp_text_input( array(
'id' => '_number_in_package',
'label' => __( 'Number of Pages', 'woocommerce' ),
'description' => __( 'This is a custom field, you can write here anything you want.', 'woocommerce' ),
'desc_tip' => 'true',
'type' => 'number'
) );
}
add_action( 'woocommerce_product_options_inventory_product_data', 'action_woocommerce_product_options_inventory_product_data' );
// Save custom field
function action_woocommerce_admin_process_product_object( $product ) {
// Isset
if ( isset( $_POST['_number_in_package'] ) ) {
// Update
$product->update_meta_data( '_number_in_package', sanitize_text_field( $_POST['_number_in_package'] ) );
}
}
add_action( 'woocommerce_admin_process_product_object', 'action_woocommerce_admin_process_product_object', 10, 1 );
// Display on single product page
function action_woocommerce_product_meta_end() {
global $product;
// Is a WC product
if ( is_a( $product, 'WC_Product' ) ) {
// Get meta
$number = $product->get_meta( '_number_in_package' );
// NOT empty
if ( ! empty ( $number ) ) {
echo '<p>' . $number . '</p>';
}
}
}
add_action( 'woocommerce_product_meta_end', 'action_woocommerce_product_meta_end', 10 );

Updating custom product meta box field - WooCommerce

I'm trying to update a custom product meta box field using the updating system from WooCommerce core. Here is my code:
The new field Shipping info
add_action( 'woocommerce_product_options_shipping', 'my_product_options_shipping' );
function my_product_options_shipping() {
global $post;
$shipping_info = get_post_meta( $post->ID, '_shipping_info', true );
woocommerce_wp_text_input(
array(
'id' => '_shipping_info',
'value' => $shipping_info,
'label' => __( 'Shipping info', 'woocommerce' ),
'placeholder' => __( 'Shipping in two days', 'woocommerce' ),
)
);
}
And this is the function that adds the new field as prop in WC_Meta_Box_Product_Data::save
add_action( 'woocommerce_admin_process_product_object', 'my_admin_process_product_object' );
function my_admin_process_product_object( $product ) {
$product->set_props(
array(
'shipping_info' => isset( $_POST['_shipping_info'] ) ? wc_clean( wp_unslash( $_POST['_shipping_info'] ) ) : null,
)
);
}
I think I'm missing a step. Shouldn't it be saved automatically from function WC_Meta_Box_Product_Data::save which is attached to woocommerce_process_product_meta?
EDIT
I found the missing step. I need to add my custom post meta in the protected array $extra_data from abstract class WC_Data.
I'm not too good at OOP, so how I can access that array to push my custom data?
I can see you're just doing $shipping_info = get_post_meta( $post->ID, '_shipping_info', true );
So why not save the trouble and just use update_post_meta
add_action( 'woocommerce_admin_process_product_object', 'my_admin_process_product_object' );
function my_admin_process_product_object( $product ) {
update_post_meta($product->get_id(), '_shipping_info', wc_clean( wp_unslash( $_POST['_shipping_info'] ) ) );
}

How to add my custom field to the Woocommerce order process (Check out form, order details and email process)

I create custome data field to my woocommerce product. I'll like to display this info (date, time and venue) on every step of the reservation. In check out page, order details and email. Could you please help me ? Find below the code I use for md custom fiels. Thanks a lot
add_action( 'woocommerce_product_options_inventory_product_data', 'woocom_inventory_product_data_custom_field' );
function woocom_Inventory_product_data_custom_field() {
// Create a custom text field
// Text Field
woocommerce_wp_text_input(
array(
'id' => 'venue',
'label' => __( 'Venue', 'woocommerce' ),
'placeholder' => 'Venue',
'desc_tip' => 'true',
'description' => __( 'Enter the location here.', 'woocommerce' )
)
);
woocommerce_wp_text_input(
array(
'id' => 'date',
'label' => __( 'Date', 'woocommerce' ),
'placeholder' => 'date',
'desc_tip' => 'true',
'description' => __( 'Enter the date here.', 'woocommerce' )
)
);
woocommerce_wp_text_input(
array(
'id' => 'time',
'label' => __( 'Time', 'woocommerce' ),
'placeholder' => 'time',
'desc_tip' => 'true',
'description' => __( 'Enter the time here.', 'woocommerce' )
)
);
}
// Hook to save the data value from the custom fields
add_action( 'woocommerce_process_product_meta', 'woocom_save_inventory_proddata_custom_field' );
/** Hook callback function to save custom fields information */
function woocom_save_inventory_produdata_custom_field( $post_id ) {
// Save Text Field
$text_field = $_POST['venue'];
if( ! empty( $text_field ) ) {
update_post_meta( $post_id, 'venue', esc_attr( $text_field ) );
}
$text_field = $_POST['date'];
if( ! empty( $text_field ) ) {
update_post_meta( $post_id, 'date', esc_attr( $text_field ) );
}
$text_field = $_POST['time'];
if( ! empty( $text_field ) ) {
update_post_meta( $post_id, 'time', esc_attr( $text_field ) );
}
}
Adding a custom field in the back-end:
This will add a new field in the Product Data section of a WooCommerce product.
/**
* Display the custom text field
* #since 1.0.0
*/
function cfwc_create_custom_field() {
$args = array(
'id' => 'custom_text_field_title',
'label' => __( 'Custom Text Field Title', 'cfwc' ),
'class' => 'cfwc-custom-field',
'desc_tip' => true,
'description' => __( 'Enter the title of your custom text field.', 'ctwc' ),
);
woocommerce_wp_text_input( $args );
}
add_action( 'woocommerce_product_options_general_product_data', 'cfwc_create_custom_field' );
Hooking the custom field function:
To ensure that the custom field displays in the correct place – in this case, it’s just on the General tab – we need to hook our function to the correct action: woocommerce_product_options_general_product_data.
If you wanted to add your custom field to a different tab, you could try actions like:
woocommerce_product_options_inventory_product_data
woocommerce_product_options_shipping
Saving the custom field value
With this code, we’ve got a really simple way to add custom fields to products, using standard WooCommerce functions and actions. All we need to do know is save the value of the field when the product is updated.
/**
* Save the custom field
* #since 1.0.0
*/
function cfwc_save_custom_field( $post_id ) {
$product = wc_get_product( $post_id );
$title = isset( $_POST['custom_text_field_title'] ) ? $_POST['custom_text_field_title'] : '';
$product->update_meta_data( 'custom_text_field_title', sanitize_text_field( $title ) );
$product->save();
}
add_action( 'woocommerce_process_product_meta', 'cfwc_save_custom_field' );
This function runs when the product is first published or when it’s updated. It looks for a value in our custom field, sanitises it, then saves it as product meta data using the CRUD methodology introduced to WooCommerce a few versions ago.
The function hooks to the woocommerce_process_product_meta action.
Adding custom values to the cart
Assuming the product successfully validates, it’ll get added to the WooCommerce cart object. We can add our own meta data to this object so that we can use it later in the process, e.g. on the cart and checkout pages and for orders and emails.
/**
* Add the text field as item data to the cart object
* #since 1.0.0
* #param Array $cart_item_data Cart item meta data.
* #param Integer $product_id Product ID.
* #param Integer $variation_id Variation ID.
* #param Boolean $quantity Quantity
*/
function cfwc_add_custom_field_item_data( $cart_item_data, $product_id, $variation_id, $quantity ) {
if( ! empty( $_POST['cfwc-title-field'] ) ) {
// Add the item data
$cart_item_data['title_field'] = $_POST['cfwc-title-field'];
}
return $cart_item_data;
}
add_filter( 'woocommerce_add_cart_item_data', 'cfwc_add_custom_field_item_data', 10, 4 );
This function hooks to woocommerce_add_cart_item_data, which filters the data passed to the cart object when a product is added to the cart. So here we check that the cfwc-title-field has a value then add that to $cart_item_data.
Displaying custom fields in the cart and checkout
Having ensured that our custom field is visible to the user in the cart and checkout forms, we now need to pass its value to the order when the user checks out.
/**
* Add custom field to order object
*/
function cfwc_add_custom_data_to_order( $item, $cart_item_key, $values, $order ) {
foreach( $item as $cart_item_key=>$values ) {
if( isset( $values['title_field'] ) ) {
$item->add_meta_data( __( 'Custom Field', 'cfwc' ), $values['title_field'], true );
}
}
}
add_action( 'woocommerce_checkout_create_order_line_item', 'cfwc_add_custom_data_to_order', 10, 4 );
We can do this very easily using the woocommerce_checkout_create_order_line_item action.

Resources