Alphabetical Index Page

You can do it like so:

// Group the categories by their FIRST LETTER.
$groups = [];
foreach ( $category_list as &$term ) {
    $letter = strtoupper( substr( $term->name, 0, 1 ) );
    if ( ! isset( $groups[ $letter ] ) ) {
        $groups[ $letter ] = [];
    }

    $groups[ $letter ][] = $term;
}

// Now display them, three groups in each row.
echo '<div class="row">';
$i = 0;
$letters = array_keys( $groups );
foreach ( $groups as $letter => $terms ) {
    $new_row = ( $i % 3 === 0 );
    if ( $i && $new_row ) {
        echo '</div><div class="row">';
    }

    // Show either "A - C", "A & B", or just a letter.
    if ( ! $i || $new_row ) {
        $range = array_slice( $letters, $i, 3 );
        if ( $end = $range[ count( $range ) - 1 ] ) {
            $sign = ( count( $range ) > 2 ) ? ' - ' : ' & ';
            $range = $letter . $sign . $end;
            echo '<h2 class="col-12">' . $range . '</h2>';
        } else {
            echo '<h2 class="col-12">' . $letter . '</h2>';
        }
    }

    echo '<div class="col-sm">';
    if ( ! empty( $terms ) ) {
        echo '<ul>';
        foreach ( $terms as $term ) {
            echo '<li>' . $term->name . '</li>';
        }
        echo '</ul>';
    }
    echo '</div>';

    $i++;
}
echo '</div>';

The output would look like so:


UPDATE

So this is the proper version, based on the layout on Carryology.com/brands/ (as of writing).

I have commented the code (although not all parts) and it shouldn’t be hard for you to make modifications to the code:

// Group the categories by their FIRST LETTER.
$letters = range( 'A', 'Z' );
$groups = [];
foreach ( $category_list as &$term ) {
    $letter = strtoupper( substr( $term->name, 0, 1 ) );
    if ( ! isset( $groups[ $letter ] ) ) {
        $groups[ $letter ] = [];
    }

    $groups[ $letter ][] = $term;
}

$cols = 3; // number of letters in a range
for ( $i = 0; $i < count( $letters ); $i++ ) {
    if ( $i % $cols === 0 ) {
        $list = array_slice( $letters, $i, $cols );
        // Start the row.
        echo '<div class="row">';

        // Show the heading. (letter range)
        $end = $list[ count( $list ) - 1 ];
        $sign = ( count( $list ) > 2 ) ? ' - ' : ' & ';
        $range = $end ? $sign . $end : '';
        // Show either "A - C", "A & B", or just a letter.
        echo '<h3 class="col-sm-2">' . $list[0] . $range . '</h3>';

        // Put all the letter terms in a single group.
        $groups2 = [];
        for ( $j = 0; $j < count( $list ); $j++ ) {
            if ( isset( $groups[ $list[ $j ] ] ) ) {
                $groups2 = array_merge( $groups2, $groups[ $list[ $j ] ] );
            }
        }

        $cols2 = 5; // number of columns in a row, excluding the heading.
        $n = count( $groups2 );
        $rows = floor( $n / $cols2 );
        $diff = $n - $rows * $cols2;
        for ( $k = 0, $l = 0; $k < $cols2; $k++ ) {
            $x = $diff ? 1 : 0;
            // Start a column.
            echo '<ul class="col-xs-4 col-sm-2">';

            // Show the group terms.
            foreach ( array_slice( $groups2, $l, $rows + $x ) as $term ) {
                echo '<li>' . $term->name . '</li>';
                $l++;
            }

            $diff = $diff ? $diff - 1 : 0;
            // Column end.
            echo '</ul>';
        }

        // Row end.
        echo '</div>';
    }
}

The output would look like so:

Leave a Comment