WooCommerce Categories, Subcategories, and Products in Separate Lists

WordPress 11 posts 2 voices

  1. I read an article here https://code.tutsplus.com/tutorials/display-woocommerce-categories-subcategories-and-products-in-separate-lists--cms-25479 about how to do this .

    I have modified the code & css to suit my purposes (wrapped image in link, added echo $term->count; to show the product count, and wrapped it all in if( !is_paged() ) {}

    The product count in Woocommerce is normally in the same line as the term name and enclosed in brackets eg Music (4) but using this the count is on a separate line not in brackets.
    Could you show a way to enclose this count in brackets, and possibly (not too important) get it to display on the same line as the term name.

    This can be seen here (just dummy data at the moment) https://amazingmomentscq.com.au/shop/

    I then added

    echo '<h2 class="shopsubtitle">';
    	 echo printf ( 'Individual Items' );
    	echo '</h2>';

    to the plugin to display a title for the next section in the page. It outputs Individual Items16 as in the page linked to above, which I can’t figure out. At first I thought it might be getting a product count in this somehow, but I removed echo $term->count; to see and it was still there.

    This is a complete copy of the plugin file. Could you have a look and see if the code is satisfactory, and suggest where the 16 might be coming from? .

    <?php
    /**
     * Plugin Name: Monomeath WooCommerce shop display
     * 
     * Description: Display products and catgeories / subcategories as two separate lists in product archive pages
     * Version: 1.0
     *
     */
    
    function monomeath_product_cats_css() {
     
        /* register the stylesheet */
        wp_register_style( 'monomeath_product_cats_css', plugins_url( 'css/style.css', __FILE__ ) );
         
        /* enqueue the stylsheet */
        wp_enqueue_style( 'monomeath_product_cats_css' );
         
    }
     
    add_action( 'wp_enqueue_scripts', 'monomeath_product_cats_css' );
    
    function monomeath_product_subcategories( $args = array() ) {
    
    if( !is_paged() ) {
        
        $parentid = get_queried_object_id();
             
    $args = array(
        'parent' => $parentid
    );
     
    $terms = get_terms( 'product_cat', $args );
     
    if ( $terms ) {
             
        echo '<ul class="product-cats">';
         
            foreach ( $terms as $term ) {
                             
                echo '<li class="category">';                 
                         
                    echo '<a href="' . esc_url( get_term_link( $term ) ) . '" class="' . $term->slug . '">';
                            echo (woocommerce_subcategory_thumbnail( $term ));
                        echo '</a>';
                     
                    echo '<h3>';
                        echo '<a href="' . esc_url( get_term_link( $term ) ) . '" class="' . $term->slug . '">';
                            echo $term->name;
                        echo '</a>';
                    echo '</h3>';
                    
                    echo $term->count;                                                    
                
                echo '</li>';
                                                                         
     
        }
         
        echo '</ul>';
     
    }
    
       
    }
    	echo '<h2 class="shopsubtitle">';
    	 echo printf ( 'Individual Items' );
    	echo '</h2>';
         
    }
    
    add_action( 'woocommerce_before_shop_loop', 'monomeath_product_subcategories', 50 );
  2. I cleaned up the code and removed some security issues. It should work correctly.

    <?php
    /**
     * Plugin Name: Monomeath WooCommerce shop display
     * 
     * Description: Display products and catgeories / subcategories as two separate lists in product archive pages
     * Version: 1.0
     *
     */
    
    function monomeath_product_cats_css() {
     
        /* register the stylesheet */
        wp_register_style( 'monomeath_product_cats_css', plugins_url( 'css/style.css', __FILE__ ) );
         
        /* enqueue the stylsheet */
        wp_enqueue_style( 'monomeath_product_cats_css' );
         
    }
     
    add_action( 'wp_enqueue_scripts', 'monomeath_product_cats_css' );
    
    function monomeath_product_subcategories( $args = array() ) {
    
    	if ( ! is_paged() ) :
    
    		$terms = get_terms( 'product_cat', array( 'parent' => get_queried_object_id() ) );
    
    		if ( $terms ) : ?>
    
    			<ul class="product-cats">
    
    			<?php foreach ( $terms as $term ) : ?>
    
    				<li class="category">
    					<a href="<?php echo esc_url( get_term_link( $term ) ); ?>"><?php woocommerce_subcategory_thumbnail( $term ); ?></a>
    
    					<h3>
    						<a href="<?php echo esc_url( get_term_link( $term ) ); ?>"><?php echo esc_html( $term->name ); ?></a> 
    						<span class="count">(<?php echo absint( $term->count ); ?>)</span>
    					</h3>
    				</li>
    
    			<?php endforeach; ?>
    
    			</ul>
    
    		<?php endif;
    
    	endif; ?>
    
    	<h2 class="shopsubtitle"><?php esc_html__( 'Individual Items' ); ?></h2>
    
    <?php }
    
    add_action( 'woocommerce_before_shop_loop', 'monomeath_product_subcategories', 50 );
  3. I cleaned up the code and removed some security issues. It should work correctly.

    <?php
    /**
     * Plugin Name: Monomeath WooCommerce shop display
     * 
     * Description: Display products and catgeories / subcategories as two separate lists in product archive pages
     * Version: 1.0
     *
     */
    
    function monomeath_product_cats_css() {
     
        /* register the stylesheet */
        wp_register_style( 'monomeath_product_cats_css', plugins_url( 'css/style.css', __FILE__ ) );
         
        /* enqueue the stylsheet */
        wp_enqueue_style( 'monomeath_product_cats_css' );
         
    }
     
    add_action( 'wp_enqueue_scripts', 'monomeath_product_cats_css' );
    
    function monomeath_product_subcategories( $args = array() ) {
    
    	if ( ! is_paged() ) :
    
    		$terms = get_terms( 'product_cat', array( 'parent' => get_queried_object_id() ) );
    
    		if ( $terms ) : ?>
    
    			<ul class="product-cats">
    
    			<?php foreach ( $terms as $term ) : ?>
    
    				<li class="category">
    					<a href="<?php echo esc_url( get_term_link( $term ) ); ?>"><?php woocommerce_subcategory_thumbnail( $term ); ?></a>
    
    					<h3>
    						<a href="<?php echo esc_url( get_term_link( $term ) ); ?>"><?php echo esc_html( $term->name ); ?></a> 
    						<span class="count">(<?php echo absint( $term->count ); ?>)</span>
    					</h3>
    				</li>
    
    			<?php endforeach; ?>
    
    			</ul>
    
    		<?php endif;
    
    	endif; ?>
    
    	<h2 class="shopsubtitle"><?php esc_html__( 'Individual Items' ); ?></h2>
    
    <?php }
    
    add_action( 'woocommerce_before_shop_loop', 'monomeath_product_subcategories', 50 );
  4. Thank you

    <h2 class="shopsubtitle"><?php esc_html__( 'Individual Items' ); ?></h2>

    doesn’t display on front end.

  5. <h2 class="shopsubtitle"></h2>
    is there in Firebug
    so changed to
    <h2 class="shopsubtitle"><?php echo esc_html__( 'Individual Items' ); ?></h2>

  6. I can add
    <h2 class="shopsubtitle"><?php echo esc_html__( 'Themes' ); ?></h2>
    to the top of this successfully which give the categories section a title, but need to change ‘Themes’ to ‘Packages’ on the following (sub- categories) page.

    Something like

    if ( is_page(shop) {
       <h2 class="shopsubtitle"><?php echo esc_html__( 'Themes' ); ?></h2>
    } else {
       <h2 class="shopsubtitle"><?php echo esc_html__( 'Packages' ); ?></h2>
    }

    if you could help with the correct syntax to achieve this.

    The Woocommerce plugin creates the ‘Shop’ page on installation and displays it using archive-product.php. The sub-categories page displays using taxonomy-product_cat.php

  7. Assuming you’re talking about the archive page for the product post type, this line:

    if ( is_page(shop) {

    Should be:

    if ( is_post_type_archive( 'product' ) ) {

    I’m not familiar enough with WC to say that for sure though. Generally speaking, the above code should work.

  8. I’m having trouble nesting

    if ( is_post_type_archive( 'product' ) ) {
       <h2 class="shopsubtitle"><?php echo esc_html__( 'Themes' ); ?></h2>
    } else {
       <h2 class="shopsubtitle"><?php echo esc_html__( 'Packages' ); ?></h2>
    }

    into the top of the cleaned up code you put together, so that either ‘Themes’ or ‘Packages’ shows before the list generated.
    What ever I do seems to throw an error.

  9. Probably the easiest way to do that is with this code:

    $subtitle = is_post_type_archive( 'product' ) ? esc_html__( 'Themes' ) : esc_html__( 'Packages' );
    
    printf( '<h2 class="shopsubtitle">%s</h2>', $subtitle );
  10. that works if included after
    if ( ! is_paged() ) :
    However, I need it to run as part of the
    if ( $terms ) : ?>
    statement so that ‘Packages’ only displays when the list generated is present.

  11. Just change this code:

    if ( $terms ) : ?>

    To this:

    if ( $terms ) : 
    
    $subtitle = is_post_type_archive( 'product' ) ? esc_html__( 'Themes' ) : esc_html__( 'Packages' );
    
    printf( '<h2 class="shopsubtitle">%s</h2>', $subtitle ); ?>

    All we’re doing is moving the ?> to the end of the PHP code.