Interlink WooCommerce products between them for cross sells settings

In WooCommerce, I would like: if Product A is added in the cross/upsells of Product B, then Product B should also automatically be added in the cross/upsells of Product A. if Product A is removed from the cross/upsells of Product B, then Product B should also automatically be removed from the cross/upsells of Product A. This is the code that I have: add_action('save_post_product', 'auto_link_cross_sells', 20, 2); function auto_link_cross_sells($post_id, $post) { // Prevent infinite loop using a transient if (get_transient('auto_cross_sell_processing')) { return; } // Get the current product's cross-sell IDs $cross_sell_ids = get_post_meta($post_id, '_crosssell_ids', true); // If there are no cross-sell IDs, exit the function if (empty($cross_sell_ids) || !is_array($cross_sell_ids)) { return; } // Set a transient to prevent an infinite loop set_transient('auto_cross_sell_processing', true, 10); // Loop through each cross-sell product ID foreach ($cross_sell_ids as $cross_sell_id) { // Check if the cross-sell product ID is valid if (!get_post($cross_sell_id)) { continue; } // Get the existing cross-sell IDs for the cross-sell product $existing_cross_sells = get_post_meta($cross_sell_id, '_crosssell_ids', true); if (!is_array($existing_cross_sells)) { $existing_cross_sells = []; } // If the current product is not already a cross-sell of the cross-sell product, add it if (!in_array($post_id, $existing_cross_sells)) { $existing_cross_sells[] = $post_id; update_post_meta($cross_sell_id, '_crosssell_ids', $existing_cross_sells); } } // Remove the transient to allow the function to run again later delete_transient('auto_cross_sell_processing'); } But it still doesn't do the job.

Comment (1)

Jese Leos

September 20, 2024

Verified user

There are some missing things in your code, as what you are trying to do is more complicated than you thought. Also, since WooCommerce 3, you should better use WC_Product available methods than WordPress Post Meta functions, as WooCommerce uses custom database tables. Here we need to use a custom field to keep track of previous history, allowing to process removed Cross-Sell IDS. Try the following code instead, that should process and interlink cross-sells between products: add_action( 'woocommerce_process_product_meta', 'process_interlinked_product_cross_sells' ); function process_inter_linked_product_cross_sells( $post_id ) { // Get current WC_Product object $product = wc_get_product( $post_id ); // Get the current product cross-sell IDs $cross_sell_ids = (array) $product->get_cross_sell_ids(); // Get current product cross-sell IDs previous history track $previous_cs_ids = (array) $product->get_meta('_previous_cs_ids'); // Check differences from history $differences_add = array_diff($cross_sell_ids, $previous_cs_ids); $differences_remove = array_diff($previous_cs_ids, $cross_sell_ids); // Added IDS case if ( $differences_add ) { // Loop through product cross-sell IDs (added) foreach ( $differences_add as $cross_sell_id ) { // get the WC_Product object from current cross sell ID $_product = wc_get_product( $cross_sell_id ); // Get cross-sell IDs for the cross-sell product $_cross_sell_ids = (array) $_product->get_cross_sell_ids(); if ( ! in_array( $post_id, $_cross_sell_ids ) ) { $_cross_sell_ids[] = $post_id; // Add the initial current product Id to the array $_product->set_cross_sell_ids( $_cross_sell_ids ); // Set updated cross-sells Ids $_product->update_meta_data( '_previous_cs_ids', $cross_sell_ids ); // Update history $_product->save(); // Sync and save } } } // Removed IDS case if ( $differences_remove ) { // Loop through product cross-sell IDs (removed) foreach ( $differences_remove as $cross_sell_id ) { // get the WC_Product object from current cross sell ID $_product = wc_get_product( $cross_sell_id ); // Get cross-sell IDs for the cross-sell product $_cross_sell_ids = (array) $_product->get_cross_sell_ids(); if ( ! in_array( $post_id, $_cross_sell_ids ) ) { unset($_cross_sell_ids[$post_id]); // Remove the initial current product Id from the array $_product->set_cross_sell_ids( $_cross_sell_ids ); // Set updated cross-sells Ids $_product->update_meta_data( '_previous_cs_ids', $cross_sell_ids ); // Update history track $_product->save(); // Sync and save } } } // Update current product history track if ( $differences_add || $differences_remove ) { // Update cross sell IDs registration history $product->update_meta_data( '_previous_cs_ids', $cross_sell_ids ); // Update history track $product->save();// Sync and save } } It should work.

You’ll be in good company