How to direct WordPress to load custom template for custom post type

For future audience sake, this notice is added.

The following answer assumed anyone have the following knowledge

  • php and basic debug knowledge: how to var_dump() or print_r()
  • WordPress Core Filter and Action known as Hooks, when and how to use them correctly
  • feel comfortable modifying theme file functions.php
  • for plugin-related development, please refer to Plugin Handbook
  • The examples are working for both putting in functions.php or in your plugin’s file. Additional logic for your own plugin required to be added by yourself since each conditions are different.

Method 1 (inside theme)

You may need to create your own single-product.php and place in your-theme/woocommerce/single-product.php;

  • prepare 2 more files in the same folder, content-single-exploded.php and content-single-other.php and place in the same folder of single-product.php

If you want to control the logic in template file single-product.php
Inside your template file, you may do the following, this will help to choose different template files for inclusion.

Do the following in your single-product.php, here is a simplified version to illustrate the concept.

// ...
<?php

if( $product->get_type() === 'exploded' ) {
wc_get_template_part( 'content', 'single-exploded' );
} else {
wc_get_template_part( 'content', 'single-other' );
}
// ...
?>

Method 2 (for both theme or plugin)

If in case you want to control template in plugin, you can use the filter template_include and do the checking you need.

You may put the following code into theme functions.php or your plugin and try to load a single product page.

* It is NOT necessary to add the following code inside any action.

// you can use this filter to control the template path and use the plugin template
add_filter( 'template_include', 'q363767_tweak_template' );
function q363767_tweak_template( $template ) {
    if( preg_match( '/single-product.php/', $template ) ) {
        // do the tweaking and update the path to single-product-explode.php with plugin directory
        // you may do var_dump here to see what is $template eg.
        // var_dump( $template );
        // $template="your-template-path";
    }

    return $template;
}

As the answer is for template file, this way will not work as expected:

function your_function() {
// not necessary to put the code here 
// XXX
// copy the above code here and run -> will NOT work
// XXX
}
add_action('woocommerce_before_single_product','your_function'); 

Because woocommerce_before_single_product is not for controlling the whole template and it is not necessary.