Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WooCommerce - How to create multiple single product template based on category?

Hello I am fairly new to woocommerce, My shop has four categories of products which use same single-product template. I want to add a fifth category of products where the product page layout is very different from already the one used.

Here's the file structure -

  • theme/woocommerce/single-product/
  • theme/woocommerce/single-product-mock/
  • theme/woocommerce/single-product-mock/title.php
  • theme/woocommerce/content-single-product-mock.php
  • theme/woocommerce/single-product.php

I created a file called content-single-product-mock.php. In single-product.php using the following code

        <?php if (has_term( 'mock', 'product_cat' )) {
            woocommerce_get_template_part( 'content', 'single-product-mock' );
        } else{
         wc_get_template_part( 'content', 'single-product' ); 
        } ?>

For the category mock it redirects to content-single-product-mock.php, but it uses the template files in single-product folder. How do change the template path in content-single-product-mock.php so that it uses the customized files in single-product-mock folder?

like image 566
user1437251 Avatar asked Sep 11 '14 14:09

user1437251


1 Answers

There is probably more than one way to do this, but they all kind of turn around the idea of filtering the template before it is included.

You could totally skip WooCommerce's simple-product.php template (without needing to override that template) and go directly to simple-product-mock.php and create everything there. You'd do that by filtering template_include.

add_filter( 'template_include', 'so_25789472_template_include' );

function so_25789472_template_include( $template ) {
  if ( is_singular('product') && (has_term( 'mock', 'product_cat')) ) {
    $template = get_stylesheet_directory() . '/woocommerce/single-product-mock.php';
  } 
  return $template;
}

You could edit single-product-mock.php to call content-single-product-mock.php and hard-code that file. Nothing requires you to keep using Woo's hooks and functions. The point of them is just to make it easy for you to customize.

Or to be really tricky, you could duplicate templates such as single-product/title.php into a single-product-mock folder... ex: single-product-mock/title.php and then any time we're on a single product template in the mock category, we'll intercept calls to the single-product/something.php template and redirect them to single-product-mock/something.php if it exists and keep pointing to the single-product/something.php if it does not. We'll do this via the woocommerce_locate_template filter.

add_filter( 'woocommerce_locate_template', 'so_25789472_locate_template', 10, 3 );

function so_25789472_locate_template( $template, $template_name, $template_path ){

    // on single posts with mock category and only for single-product/something.php templates
    if( is_product() && has_term( 'mock', 'product_cat' ) && strpos( $template_name, 'single-product/') !== false ){

        // replace single-product with single-product-mock in template name
        $mock_template_name = str_replace("single-product/", "single-product-mock/", $template_name );

        // look for templates in the single-product-mock/ folder
        $mock_template = locate_template(
            array(
                trailingslashit( $template_path ) . $mock_template_name,
                $mock_template_name
            )
        );

        // if found, replace template with that in the single-product-mock/ folder
        if ( $mock_template ) {
            $template = $mock_template;
        }
    }

    return $template;
}

Update to filter wc_get_template instead.

/**
 * Change wc template part for product with a specific category
 *
 * @param  string $templates
 * @param  string $slug
 * @param  string $name
 * @return string
 */
function so_25789472_get_template_part( $template, $slug, $name ) {
  if ( $slug == 'content' && $name = 'single-product' && has_term( 'test', 'product_cat' ) ) {
    $template = locate_template( array( WC()->template_path() . 'content-single-product-test.php' ) );
  } 
  return $template;
}
add_filter( 'wc_get_template_part', 'so_25789472_get_template_part', 10, 3 );
like image 87
helgatheviking Avatar answered Nov 09 '22 04:11

helgatheviking