How to Add More Custom Field in Linked Product of Woocommerce

How to add more custom field in Linked Product of Woocommerce

There are several things missing in your code above.

  1. The hook you have used on the first line, do not exist. The right hook is called woocommerce_product_options_related
  2. The code where you've designed your custom field, is not inside any function.
  3. You are creating a standard text-field. If you want a "Select Product"-dropdown, you should use another approach.
    This should be inside that function that you're using in the hook.
  4. You are missing a hook and a function the actually save the data from your custom field


1. Finding the right hook/action

To find the right hook to use, just search for "woocommerce_product_options_" inside the WoocCommerce plugin, and about 6 PHP-files should appear. One of those files is called "html-product-data-linked-products.php". This file contains all the existing options in that specific WooCommerce section. It also contains the hook used to display those options.

Open the file and check it out. The hook is at the bottom of the page

Full Path:
/wp-content/plugins/woocommerce/includes/admin/metaboxes/views/



2. Creating the dropdown

To create a select-dropdown including a product search, you need a much different code than the one above.

The spare some time, you can just copy-paste one of the existing options, in the file mentioned above, and then modify it, to your needs.

All this should be placed inside a function called: woocom_linked_products_data_custom_field().

2.1. Modify the ID/name

The first things you need to modify in the code, is of course the unique ID/name of the field.
This is placed in the label-tag (for) and the select-tag (id and name).

In your example the ID/name should be upsizing_products and the label-text Upsizing Products:

<label for="upsizing_products"><?php _e( 'Upsizing Product', 'woocommerce' ); ?></label>
<select class="wc-product-search" multiple="multiple" style="width: 50%;" id="upsizing_products" name="upsizing_products[]" data-placeholder="<?php esc_attr_e( 'Search for a product…', 'woocommerce' ); ?>" data-action="woocommerce_json_search_products_and_variations" data-exclude="<?php echo intval( $post->ID ); ?>">

Note: Don't forget to put an [] and the end of the name-tag, or your data will not be stored.

2.2. Show already chosen products

The next thing, is to show and highligt already chosen products in the WooCommerce section and the dropdown it self.

To do this replace the $product_ids-variable and the entire line with:

$product_ids = get_post_meta( $post->ID, '_upsizing_products_ids', true );

With this instead, the product id's is retrieved from your custom field in the database instead of one of the existing options (cross_sell_ids for example).

Note: The _upsizing_products_ids is the meta-key name in the database. The meta-value related to this key, contains all your field data. This is used to store and retrieve the custom field.

2.3. Display the field in the WooCommerce section

Lastly, the function should be properly hooked, so it can be displayed in the Linked Products section:

add_action( 'woocommerce_product_options_related', 'woocom_linked_products_data_custom_field' );


3. Save and store the data

Now your custom field is displayed inside the right section. The next thing is to save and store the data in the database.

Inside a new function, use $_POST to retrieve the data from the field, and update_post_meta to store the data in the database containing the post-ID, the unique field-id/name (meta-key) and the data it self (meta-value).

function woocom_linked_products_data_custom_field_save( $post_id ){
$product_field_type = $_POST['upsizing_products'];
update_post_meta( $post_id, '_upsizing_products_ids', $product_field_type );
}
add_action( 'woocommerce_process_product_meta', 'woocom_linked_products_data_custom_field_save' );

Here's the full code. Put it inside your themes functions.php or a plugin file:

// Display the custom fields in the "Linked Products" section
add_action( 'woocommerce_product_options_related', 'woocom_linked_products_data_custom_field' );

// Save to custom fields
add_action( 'woocommerce_process_product_meta', 'woocom_linked_products_data_custom_field_save' );

// Function to generate the custom fields
function woocom_linked_products_data_custom_field() {
global $woocommerce, $post;
?>
<p class="form-field">
<label for="upsizing_products"><?php _e( 'Upsizing Product', 'woocommerce' ); ?></label>
<select class="wc-product-search" multiple="multiple" style="width: 50%;" id="upsizing_products" name="upsizing_products[]" data-placeholder="<?php esc_attr_e( 'Search for a product…', 'woocommerce' ); ?>" data-action="woocommerce_json_search_products_and_variations" data-exclude="<?php echo intval( $post->ID ); ?>">
<?php
$product_ids = get_post_meta( $post->ID, '_upsizing_products_ids', true );

foreach ( $product_ids as $product_id ) {
$product = wc_get_product( $product_id );
if ( is_object( $product ) ) {
echo '<option value="' . esc_attr( $product_id ) . '"' . selected( true, true, false ) . '>' . wp_kses_post( $product->get_formatted_name() ) . '</option>';
}
}
?>
</select> <?php echo wc_help_tip( __( 'Select Products Here.', 'woocommerce' ) ); ?>
</p>

<?php
}

// Function the save the custom fields
function woocom_linked_products_data_custom_field_save( $post_id ){
$product_field_type = $_POST['upsizing_products'];
update_post_meta( $post_id, '_upsizing_products_ids', $product_field_type );
}

To display the stored data use _upsizing_products_ids:

echo get_post_meta( $post->ID, 'my-field-slug', true );

Check out this guide Mastering WooCommerce Products
Custom Fields for more information about Custom Fields for WooCommerce.

Custom field in Linked Products woocommerce

you should look some woocommerce documentation. https://docs.woocommerce.com/documentation/plugins/woocommerce/woocommerce-codex/theming/

you can follow these steps.

the woocommerce>templates>cart>cart.php is the cart page.
you will find something like this.

foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'],
$cart_item, $cart_item_key );
$product_id = apply_filters( 'woocommerce_cart_item_product_id',
$cart_item['product_id'], $cart_item, $cart_item_key );

loop display the products you added to the cart.Variable $product_id of the loop have the id of each product you added the the cart. now you can insert your custom field code here

echo get_post_meta( $product_id, 'my-field-slug', true );

it will look something like this.

foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'],
$cart_item, $cart_item_key );
$product_id = apply_filters( 'woocommerce_cart_item_product_id',
$cart_item['product_id'], $cart_item, $cart_item_key );

// Display Custom Field Value
// my-field-slug should be change according to your slug
echo get_post_meta( $product_id, 'my-field-slug', true );
}

Add custom field to product inventory tab and display value only on WooCommerce admin order edit page

To display the meta data in WooCommerce admin order edit pages only, you can use the woocommerce_before_order_itemmeta hook

To save fields you can use the woocommerce_admin_process_product_object hook, opposite the outdated woocommerce_process_product_meta hook

So you get:

// Add custom field
function action_woocommerce_product_options_inventory_product_data() {
woocommerce_wp_text_input( array(
'id' => '_custom_text_field',
'label' => __( 'Custom Text Field', 'woocommerce' ),
'description' => __( 'This is a custom field, you can write here anything you want.', 'woocommerce' ),
'desc_tip' => 'true',
'placeholder' => __( 'Custom text', 'woocommerce' )
) );
}
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['_custom_text_field'] ) ) {
// Update
$product->update_meta_data( '_custom_text_field', sanitize_text_field( $_POST['_custom_text_field'] ) );
}
}
add_action( 'woocommerce_admin_process_product_object', 'action_woocommerce_admin_process_product_object', 10, 1 );

// Add before item meta
function action_woocommerce_before_order_itemmeta( $item_id, $item, $product ) {
// Only on backend order edit pages
if ( ! is_admin() ) return;

// Targeting line items type only
if ( $item->get_type() !== 'line_item' ) return;

// Finds whether a variable is null
$product = is_null( $product ) ? $item->get_product() : $product;

// Get meta
$value = $product->get_meta( '_custom_text_field' );

// NOT empty
if ( ! empty ( $value ) ) {
echo '<p>' . $value . '</p>';
}
}
add_action( 'woocommerce_before_order_itemmeta', 'action_woocommerce_before_order_itemmeta', 10, 3 );

Get the id from a product custom field with linked products in WooCommerce

Your code #2 should better be (as this custom field is an array of sample product ids):

add_action( 'woocommerce_single_product_summary', 'custom_sample_product_button_after_cart', 30 );
function custom_sample_product_button_after_cart() {
global $product;

$sample_products_ids = (array) $product->get_meta('_sample_products_ids');

$sample_products_ids = implode( ', ', $sample_products_ids );

echo '<div>Testing with this to get the IDs of the sample products, which are: ' . $sample_products_ids . '</div>';
}

And then you code #3 should be (Here we get the first sample product):

add_action( 'woocommerce_single_product_summary', 'custom_button_after_product_summary', 30 );
function custom_sample_product_button_after_cart() {
global $product;

$sample_products_ids = (array) $product->get_meta('_sample_products_ids');

// Display an add to cart button for the first product sample
echo '<a href="https://example.com/page_of_product_a/?add-to-cart=' . reset(sample_products_ids); . '&quantity=1">' . __("Add Product B") . '</a>';
}

Woocommerce Product Export : add multiple meta fields using function add_export_data( $value, $product )

Answering my own question here, and a suggestion that may help others.

Yes, I was correct in my code snippet above.
It does work as expected.

@CBroe was correct:

Maybe start by double-checking the spellings everywhere. The name of
the hooks seem to be related directly to the column slugs, so even the
tiniest misspelling there will likely cause it to not call any
function for the field in question.

My issues were essentially finger trouble

I have 11 Custom Fields.

That gets a little unwieldy when the custom_field_slug references get separated by other code.

So I am adding here

  • a breakdown to explain what steps are needed
  • and a formatting suggestion that has made life a lot easier for me to scan across a whole group of related items to make sure I haven't got any typos

STEP 1 : Add Custom Columns to Array for Mapping

/* [ mycode ] EXPORT : ADD custom columns to Exporter
------------------------------------------------------------------------------*/

/**
* Add the custom columns to the exporter and the exporter column menu.
*
* @param array $columns
* @return array $columns
*
*/

function add_export_columns( $columns ) {

// ---------------------------------------------------- Company SYSTEM Fields
// column slug > column name
$columns['company_system_item_code'] = 'Company SYSTEM Item Code';
$columns['company_system_item_description'] = 'Company SYSTEM Item Description';
$columns['company_system_item_category'] = 'Company SYSTEM Item Category';
$columns['company_system_item_unit_weight'] = 'Company SYSTEM Item Unit Weight';
$columns['company_system_item_unit_price'] = 'Company SYSTEM Item Unit Price';

// ---------------------------------------------------- Company WEBSITE Fields
// column slug > column name
$columns['company_website_discount_percent'] = 'Company WEBSITE Discount Percent';
$columns['company_website_item_unit_price'] = 'Company WEBSITE Item Unit Price';
$columns['company_website_item_minimum_units'] = 'Company WEBSITE Item Minimum Units';

// ---------------------------------------------------- Company SUPPLIER Fields
// column slug > column name
$columns['company_supplier_item_code'] = 'Company_SUPPLIER Item Code';
$columns['company_supplier_item_description'] = 'Company SUPPLIER Item Description';
$columns['company_supplier_item_unit_price'] = 'Company SUPPLIER Item Unit Price';

return $columns;
}
add_filter( 'woocommerce_product_export_column_names', 'add_export_columns' );
add_filter( 'woocommerce_product_export_product_default_columns', 'add_export_columns' );

STEP 2 : All the Export Data Functions

/* [ mycode ] EXPORT : GET data to be exported
------------------------------------------------------------------------------*/

/**
*
* Functions to provide the data to be exported for one item in EACH column.
*
*/

// ------------------------------------------------------- Company SYSTEM Fields
function add_export_data_company_system_item_code( $value, $product ) {
$value = $product->get_meta( 'company_system_item_code', true, 'edit' );
return $value;
}
function add_export_data_company_system_item_description( $value, $product ) {
$value = $product->get_meta( 'company_system_item_description', true, 'edit' );
return $value;
}
function add_export_data_company_system_item_category( $value, $product ) {
$value = $product->get_meta( 'company_system_item_category', true, 'edit' );
return $value;
}
function add_export_data_company_system_item_unit_weight( $value, $product ) {
$value = $product->get_meta( 'company_system_item_unit_weight', true, 'edit' );
return $value;
}
function add_export_data_company_system_item_unit_price( $value, $product ) {
$value = $product->get_meta( 'company_system_item_unit_price', true, 'edit' );
return $value;
}

// ------------------------------------------------------- Company WEBSITE Fields
function add_export_data_company_website_discount_percent( $value, $product ) {
$value = $product->get_meta( 'company_website_discount_percent', true, 'edit' );
return $value;
}
function add_export_data_company_website_item_unit_price( $value, $product ) {
$value = $product->get_meta( 'company_website_item_unit_price', true, 'edit' );
return $value;
}
function add_export_data_company_website_item_minimum_units( $value, $product ) {
$value = $product->get_meta( 'company_website_item_minimum_units', true, 'edit' );
return $value;
}

// ------------------------------------------------------- Company SUPPLIER Fields
function add_export_data_company_supplier_item_code( $value, $product ) {
$value = $product->get_meta( 'company_supplier_item_code', true, 'edit' );
return $value;
}
function add_export_data_company_supplier_item_description( $value, $product ) {
$value = $product->get_meta( 'company_supplier_item_description', true, 'edit' );
return $value;
}
function add_export_data_company_supplier_item_unit_price( $value, $product ) {
$value = $product->get_meta( 'company_supplier_item_unit_price', true, 'edit' );
return $value;
}

STEP 3 : All the Filters

/**
*
* Add filters to hook in for EACH column
*
*/

// ------------------------------------------------------- Company SYSTEM Fields
add_filter( 'woocommerce_product_export_product_column_company_system_item_code' , 'add_export_data_company_system_item_code', 10, 2 );
add_filter( 'woocommerce_product_export_product_column_company_system_item_description' , 'add_export_data_company_system_item_description', 10, 2 );
add_filter( 'woocommerce_product_export_product_column_company_system_item_category' , 'add_export_data_company_system_item_category', 10, 2 );
add_filter( 'woocommerce_product_export_product_column_company_system_item_unit_weight' , 'add_export_data_company_system_item_unit_weight', 10, 2 );
add_filter( 'woocommerce_product_export_product_column_company_system_item_unit_price' , 'add_export_data_company_system_item_unit_price', 10, 2 );

// ------------------------------------------------------- Company WEBSITE Fields
add_filter( 'woocommerce_product_export_product_column_company_website_discount_percent' , 'add_export_data_company_website_discount_percent', 10, 2 );
add_filter( 'woocommerce_product_export_product_column_company_website_item_unit_price' , 'add_export_data_company_website_item_unit_price', 10, 2 );
add_filter( 'woocommerce_product_export_product_column_company_website_item_minimum_units', 'add_export_data_company_website_item_minimum_units', 10, 2 );

// ------------------------------------------------------- Company SUPPLIER Fields
add_filter( 'woocommerce_product_export_product_column_company_supplier_item_code' , 'add_export_data_company_supplier_item_code', 10, 2 );
add_filter( 'woocommerce_product_export_product_column_company_supplier_item_description' , 'add_export_data_company_supplier_item_description', 10, 2 );
add_filter( 'woocommerce_product_export_product_column_company_supplier_item_unit_price' , 'add_export_data_company_supplier_item_unit_price', 10, 2 );

NOTE also the white space padding I used to align the components.

When you have many column slugs of different length, it's quite awkward to scan for errors.

If you don't have every hook and every function named correctly with the appropriate column slugs, then you won't get the expected results.


Hopefully this worked example may be useful for someone else in future.

Show custom field as external link in WooCommerce

You can use the following for this:

The conditions ensure that the text is always displayed (if not empty), the 2nd condition makes it a clickable link if the designer url field is not empty, otherwise just the designer name will be shown.

HTML <a> target Attribute

  • _blank Opens the linked document in a new window or tab
  • _self Opens the linked document in the same frame as it was clicked (this is default)
  • _parent Opens the linked document in the parent frame
  • _top Opens the linked document in the full body of the window
function display_designer_fields_value() {
global $product;

// Is a WC product
if ( is_a( $product, 'WC_Product' ) ) {
// Get meta
$designer_name = $product->get_meta( '_designer_name' );
$designer_url = $product->get_meta( '_designer_url' );

// NOT empty
if ( ! empty( $designer_name ) ) {
$output = '<span id="value-on-single-product" class="custom-field">';

// NOT empty
if ( ! empty ( $designer_url ) ) {
$output .= '<a href="' . $designer_url . '" target="_blank">' . $designer_name . '</a></span>';
} else {
$output .= $designer_name . '</span>';
}

echo $output;
}
}
}
add_action( 'woocommerce_before_add_to_cart_form', 'display_designer_fields_value' );
add_action( 'woocommerce_after_shop_loop_item', 'display_designer_fields_value' );


Related Topics



Leave a reply



Submit