Search code examples
phpcsswordpresswoocommerceproduct

Embed each term from a comma separated string of product attributes in a span tag


In an online store on WooCommerce, I use code that displays certain product attributes on archive/category pages.

add_action( 'woocommerce_before_shop_loop_item_title', 'new_template_loop_product_meta', 20 );
function new_template_loop_product_meta() {
    global $product;

    $attrs_by_cats = [
        20 => [ 'pa_size' ],

    ];

    $attr_list = [
        'Size' => 'pa_size',
    ];

    if ( ! is_object( $product ) ) {
        $product = wc_get_product( get_the_id() );
    }

    $cats = $product->get_category_ids();

    if ( ! is_array( $cats ) ) {
        return;
    }

    $attrs = [];

    foreach ( $cats as $cat ) {
        if ( isset( $attrs_by_cats[ $cat ] ) ) {
            $attrs[] = $attrs_by_cats[ $cat ];
        }
    }

    $allowed_attrs = array_unique( array_merge( [], ...$attrs ) );

    echo '<div class="custom-attributes">';

    foreach ( $attr_list as $attr_title => $attr_name ) {
        if ( in_array( $attr_name, $allowed_attrs, true ) ) {
            show_attribute( $product, $attr_title, $attr_name );
        }
    }

    echo '</div>';
}
function show_attribute( $product, $attr_title, $attr_name ) {
    if ( 'sku' === $attr_name ) {
        $attr = (string) $product->get_sku();
    } else {
        $attr = $product->get_attribute( $attr_name );
    }

    if ( '' === $attr ) {
        return;
    }

    echo '<span class="custom-attributes-text">Size: ' . esc_html( $attr ) . '</span>';
}

Right now the code displays the “Size” attribute in a single list/array, comma separated. I need to show the sizes individually and without comma, i.e. wrap each of the sizes in a span and make a border for each one. It's like this - https://prnt.sc/V9LcNuB2kp9B

I've looked at different options on this site for placing attributes on the archive/categories pages, but nothing fits.

How can this be implemented? I will be glad to help with the code!


Solution

  • You can use PHP explode() function to convert the comma separated string of Size attributes term names to an array of term names… Then you can easily embed each size (term) individually in a <span> tag, via a foreach loop. To finish, implode() PHP function will allow converting back the array of formatted HTML terms back into a string.

    Try to replace your last function with the following:

    function show_attribute( $product, $attr_title, $attr_name ) {
        if ( 'sku' === $attr_name ) {
            $attr = (string) esc_html( $product->get_sku() );
        } else {
            $attr = $product->get_attribute( $attr_name );
    
            if ( ! $attr ) {
                return;
            }
            $attr = explode( ', ', $attr ); // convert the coma separated string to an array
    
            $attr_arr = []; // Initialize
    
            // Loop through the term names
            foreach ( $attr as $term_name ) {
                // Embed each term in a span tag
                $attr_arr[] = sprintf('<span class="attr-term">%s</span>', $term_name);
            }
            // Convert back the array of formatted html term names to a string
            $attr = implode(' ', $attr_arr);
        }
    
        if ( '' === $attr ) {
            return;
        }
    
        printf( '<div class="custom-attributes-text">%s: %s</div>', $attr_title, $attr);
    }
    

    Then for CSS styling you can add the following rules (adapting them to your needs):

    .custom-attributes-text {margin-bottom:12px; color:black;}
    .custom-attributes-text > span.attr-term {display:inline-block; border:solid 1px #cccccc; padding:0 5px; margin:0 2px;}
    

    You will get something like:

    enter image description here