WooCommerce – Load Templates From Plugin For All Template Files

WooCommerce uses the template_include filter/hook to load main templates like archive-product.php and single-product.php. And here’s the class which handles main templates.

And there’s a filter in that class which you can use to capture the default file (name) which WooCommerce loads based on the current request/page — e.g. single-product.php for single product pages.

You can’t, however, simply hook to that filter, return a custom template path and expect it to be used (because the path has to be relative to the active theme folder). But you can do something like in the second snippet below (which is tried & tested working on WordPress 5.2.2 with WooCommerce 3.6.5, the latest version as of writing):

  1. First, a helper function:

    // Helper function to load a WooCommerce template or template part file from the
    // active theme or a plugin folder.
    function my_load_wc_template_file( $template_name ) {
        // Check theme folder first - e.g. wp-content/themes/my-theme/woocommerce.
        $file = get_stylesheet_directory() . '/woocommerce/' . $template_name;
        if ( @file_exists( $file ) ) {
            return $file;
        }
    
        // Now check plugin folder - e.g. wp-content/plugins/my-plugin/woocommerce.
        $file="full/path/to/your/plugin/" . 'woocommerce/' . $template_name;
        if ( @file_exists( $file ) ) {
            return $file;
        }
    }
    
  2. To override main WooCommerce templates (e.g. single-product.php):

    add_filter( 'woocommerce_template_loader_files', function( $templates, $template_name ){
        // Capture/cache the $template_name which is a file name like single-product.php
        wp_cache_set( 'my_wc_main_template', $template_name ); // cache the template name
        return $templates;
    }, 10, 2 );
    
    add_filter( 'template_include', function( $template ){
        if ( $template_name = wp_cache_get( 'my_wc_main_template' ) ) {
            wp_cache_delete( 'my_wc_main_template' ); // delete the cache
            if ( $file = my_load_wc_template_file( $template_name ) ) {
                return $file;
            }
        }
        return $template;
    }, 11 );
    
  3. To override WooCommerce template parts (retrieved using wc_get_template_part()):

    add_filter( 'wc_get_template_part', function( $template, $slug, $name ){
        $file = my_load_wc_template_file( "{$slug}-{$name}.php" );
        return $file ? $file : $template;
    }, 10, 3 );
    
  4. To override other WooCommerce templates (retrieved using wc_get_template() or wc_locate_template()):

    add_filter( 'woocommerce_locate_template', function( $template, $template_name ){
        $file = my_load_wc_template_file( $template_name );
        return $file ? $file : $template;
    }, 10, 2 );
    

Btw, there’s also the woocommerce_template_path filter for those of you who’re just looking to change the default WooCommerce templates folder (woocommerce) in the active theme folder.

Leave a Comment