4
votes

I've been pulling my hair out with this all day, please forgive the short description, I just need to validate my sanity!!

As the title says, I'm trying to create two or three different single-product layouts within woocommerce. The minimum is trying to achieve would be to have multiple single-product folders each with their own name and configurations.

No matter which way I try to override the single-product.php and make this file use logic to check for the product_cat and give out templates accordingly, I either the page not loading or what I write is skipped over and the default is loaded.

So far I've been through the following methods multiple times, trying to piece together what may be outdated code or otherwise causing all the fuss:

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

Woocommerce single product - template by categories

Creating a different template file for certain Product Categories - Wordpress/Woocommerce?

I was more hoping someone may know something about this that I'm obviously missing as there are many articles out there on what to try and most claim success but I'm unable to do so.

[Update] using template_include code from @helgatheviking

No success just yet but here's where I'm up to;

File structure team-shops is the category I'm trying to get

  • /mytheme/woocommerce/single-product.php - no changes
  • /mytheme/woocommerce/content-single-product.php
  • /mytheme/woocommerce/single-product-team-shops.php - changed line 37 to<?php wc_get_template_part( 'content', 'single-product-team-shops' ); ?>
  • /mytheme/woocommerce/content-single-product-team-shops.php - added additional id to #product-id (line 39)
  • /mytheme/woocommerce/single-product-team-shops/ folder with all single product files to change.

As I said above this isn't working but hopefully with what I've provided the problem may be more obvious.

Thanks again for any help :)

[Think I've got it]

Ok so I think I've something that works, at least for now it seems to, still have some further testing to do but any thoughts more than welcome, this is what I've got so far along with a single-product-team-shops folder in my theme

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

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

    $term_id = 2854;
    $taxonomy_name = 'product_cat';
    $term_children = get_term_children( $term_id, $taxonomy_name );

    foreach ( $term_children as $child ) {

    // on single posts with mock category and only for single-product/something.php templates
    if( is_product() && has_term( $child, '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-team-shops/", $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;
}
2
I was going to say this sounds awfully familiar, but there's my answer in your first link here. My template_include method ought to get you up an running with multiple single product templates. It doesn't look out of date (though i can't retest it right now), so please share your version of the code and explain where you are storing your templates.helgatheviking
thank @helgatheviking ill get everything setup as per your link and get back to you, thanks for reaching out!blackhill24
updated @helgathevikingblackhill24
hey, @helgatheviking another update, the code above does work, however, only affects content-single-product.PHP, forgive my ignorance here. The second method you suggest, however, works perfectly so I currently have that up and running. The only issue I've come across using this method is that "has_term" doesn't let me use a parent, I've been trying to use "get_term_children" so far with no success, I'll update that code shortly, thanks again :)blackhill24
Well if you use the same action hooks in your content-single-product-custom.php you will get the same look as the default custom-single-product.php.helgatheviking

2 Answers

7
votes

Use a single-product-custom.php template for any product in the "custom" category:

add_filter( 'template_include', 'so_43621049_template_include' );

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

NB: If you use the same action hooks in your single-product-custom.php template you will get the same look as the default single-product.php. You could 'rename' all the hooks and then could add existing functions (such as those for add to cart buttons, etc) to the new hooks in order to achieve a totally custom look.

0
votes

thanks for this, I have about 50 Categories, is there away of simplifying the above for multiple custom product pages, this works for 2.

add_filter( 'template_include', 'bsl_single_product_template_include', 50, 1 );
function bsl_single_product_template_include( $template ) {
    if ( is_singular('product') && (has_term( 'Battery Scissor Lifts', 'product_cat')) ) {
        $template = get_stylesheet_directory() . '/woocommerce/single-product-battery-scissor-lifts.php';
    } 
    return $template;
}

add_filter( 'template_include', 'dfsl_single_product_template_include', 50, 1 );
function dfsl_single_product_template_include( $template ) {
    if ( is_singular('product') && (has_term( 'Diesel Fuel Scissor Lifts', 'product_cat')) ) {
        $template = get_stylesheet_directory() . '/woocommerce/single-product-diesel-fuel-scissor-lifts.php';
    } 
    return $template;
}