d1ch0t0my d1ch0t0my - 2 months ago 7
PHP Question

Shortcode - Display all terms of an attribute into an ordered list by alphabetical letters

I've created a simple shortcode to output attribute terms and link to their respective archives. I'd like to be able to split the results by letter so that they output as follows:

A
Adidas
Askwith

B
Bonham
Burberry


...which would in HTML look like this:

<span id="a">A</span>
<ul class="brandlist">
<li><a href="/brand/adidas">Adidas</a></li>
<li><a href="/brand/askwith">Askwith</a></li>
</ul>

<span id="b">B</span>
<ul class="brandlist">
<li><a href="/brand/bonham">Bonham</a></li>
<li><a href="/brand/burberry">Burberry</a></li>
</ul>


But I'm at a bit of a loss on how to do this. I've read a few articles that suggest creating a new custom taxonomy for the letters but that seems to be a long way around to doing something that I hope is solvable in a simpler way.

Here's the shortcode I've created so far:

function brands_output( $atts ){

ob_start();
echo '<ul class="brandlist">';

$terms = get_terms( array(
'taxonomy' => 'pa_brand',
'orderby' => 'name',
'hide_empty' => false,
)
);

foreach ( $terms as $term ) {
$brand = $term->name;
$slug = $term->slug;

echo '<li><a href="/brand/'.$slug.'/">'.$brand.'</a></li>';
}

echo '</ul>';
$output = ob_get_clean();
return $output;

}
add_shortcode( 'showbrands', 'brands_output' );


How an I achieve this?

Thanks

Answer

Here is your fully functional shortcode. I have test it with a different set of terms and it works perfectly (so I hope that yours is correct and working too).

First I prepare the data in a bi-dimentional array with the alphabetical letters on level 1 and the corresponding terms pair name/slug on level2.

After I iterate in this bi-dimentional array to make the display you want to haveā€¦

Here is the code:

if (!function_exists('showbrands')) {

    function showbrands(){

        $term_arr = array();

        $terms = get_terms( array(
            'taxonomy' => 'pa_brand',
            'orderby' => 'name',
            'hide_empty' => false,
        ) );

        foreach ( $terms as $term ) {
            $brand = $term->name;
            $slug = $term->slug;

            // Getting the first letter of $brand term name
            $letter = substr($brand, 0, 1);

            // PREPARING DATA IN A BI DIMENSIONAL ARRAY

            // Inserting the $letter in an array just once (array level 1)
            // Inserting for each letter all the corresponding pairs "$brand => $slug" (array level 2)
            if(!array_key_exists($letter, $term_arr))
                $term_arr[$letter] = array($slug => $brand);
            else
                $term_arr[$letter][$slug] = $brand;
        }

        $output = '<div class="brandlist-container">';

        // ITERATING IN THE BI DIMENTIONAL $TERM_ARR ARRAY 

        // first level the letters
        foreach( $term_arr as $key_letter => $terms_in_letter ){
            $output .= '<span id="'. strtolower( $key_letter ) .'">'. $key_letter .'</span>
                  <ul class="brandlist">';

            // second level the $brand / $slug pairs
            foreach( $terms_in_letter as $key => $value ){
                $output .= '<li><a href="/brand/'.$key.'/">'.$value.'</a></li>';
            }
            $output .= '</ul>';
        }
        $output .= '</div>';

        return $output;
    }

    add_shortcode( 'showbrands', 'showbrands' );

}

This code goes on function.php file of your active child theme (or theme) or in any plugin file.

This code is tested and works.