Search code examples
phpwordpresswoocommerceformatsku

WooCommerce Products - Always ensure that SKU contains 13 digits


When we create or update a product in WooCommerce, if the SKU (_sku) field has less than 13 digits, we have to fill in zeros to always reach 13 digits.

  • For instance, if the field contains nothing, then we should add 13 zeros in the field.

  • For instance, if the field contains 123456, then we should add 7 zeros before it.

  • For instance, if the field contains 123456789, then we should add 3 zeros before it.

  • For instance, if the field contains 1234567891234, then we should do nothing because it has 13 digits.

I have the below code, which partially works, meaning that it effectively adjust the number of digits in the backend, but when I search for the product based on SKU in the frontend, I'm not finding the product, so I guess that it doesn't work fine. Any one to help on this? Thanks

function ensure_13_digit_sku($sku) {
    return str_pad($sku, 13, '0', STR_PAD_LEFT);
}
function ensure_sku_length_on_save($post_id, $post, $update) {
    if ($post->post_type !== 'product') {
        return;
    }
    $sku = get_post_meta($post_id, '_sku', true);
    if (!$sku || strlen($sku) < 13) {
        $new_sku = ensure_13_digit_sku($sku);
        update_post_meta($post_id, '_sku', $new_sku);
    }
}
add_action('save_post', 'ensure_sku_length_on_save', 10, 3);

Solution

  • Since WooCommerce 3, you should use WC_Product set_sku() setter method and admin product related hooks, to adjust the product SKU like:

    function ensure_13_digit_sku( $sku ) {
        return str_pad($sku, 13, '0', STR_PAD_LEFT);
    }
    
    add_action('woocommerce_admin_process_product_object', 'pre_process_product_sku');
    function pre_process_product_sku( $product ) {
        $sku = isset($_POST['_sku']) ? wc_clean( wp_unslash($_POST['_sku']) ) : '';
    
        $product->set_sku( ensure_13_digit_sku($sku) );
    }
    
    add_action('woocommerce_admin_process_variation_object', 'pre_process_variation_sku');
    function pre_process_variation_sku( $variation, $i ) {
        $sku = isset($_POST['variable_sku'][$i]) ? wc_clean( wp_unslash($_POST['variable_sku'][$i]) ) : '';
    
        $variation->set_sku( ensure_13_digit_sku($sku) );
    }
    

    Code goes in functions.php file of the active child theme (or active theme). It should work.

    Try always to avoid using WordPress post meta functions and hooks, as they don't refresh or synchronize data.